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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: ui/display/manager/display_preferences.cc
diff --git a/ui/display/manager/display_preferences.cc b/ui/display/manager/display_preferences.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f70236f4be1e21f011f77e5954615816c66e514d
--- /dev/null
+++ b/ui/display/manager/display_preferences.cc
@@ -0,0 +1,510 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/display/manager/display_preferences.h"
+
+#include <stddef.h>
+
+#include "ash/shell.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/sys_info.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/common/pref_names.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/scoped_user_pref_update.h"
+#include "components/user_manager/user_manager.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+#include "ui/display/display.h"
+#include "ui/display/manager/display_layout_store.h"
+#include "ui/display/manager/display_manager_utilities.h"
+#include "ui/display/manager/display_pref_util.h"
+#include "ui/display/manager/json_converter.h"
+#include "ui/display/types/display_constants.h"
+#include "ui/gfx/geometry/insets.h"
+#include "url/url_canon.h"
+#include "url/url_util.h"
+
+#include "services/preferences/public/cpp/pref_client_store.h"
+#include "services/preferences/public/interfaces/preferences.mojom.h"
+
+namespace display {
+namespace {
+
+const char kInsetsTopKey[] = "insets_top";
+const char kInsetsLeftKey[] = "insets_left";
+const char kInsetsBottomKey[] = "insets_bottom";
+const char kInsetsRightKey[] = "insets_right";
+
+const char kTouchCalibrationWidth[] = "touch_calibration_width";
+const char kTouchCalibrationHeight[] = "touch_calibration_height";
+const char kTouchCalibrationPointPairs[] = "touch_calibration_point_pairs";
+
+// This kind of boilerplates should be done by base::JSONValueConverter but it
+// doesn't support classes like gfx::Insets for now.
+// TODO(mukai): fix base::JSONValueConverter and use it here.
+bool ValueToInsets(const base::DictionaryValue& value, gfx::Insets* insets) {
+ DCHECK(insets);
+ int top = 0;
+ int left = 0;
+ int bottom = 0;
+ int right = 0;
+ if (value.GetInteger(kInsetsTopKey, &top) &&
+ value.GetInteger(kInsetsLeftKey, &left) &&
+ value.GetInteger(kInsetsBottomKey, &bottom) &&
+ value.GetInteger(kInsetsRightKey, &right)) {
+ insets->Set(top, left, bottom, right);
+ return true;
+ }
+ return false;
+}
+
+void InsetsToValue(const gfx::Insets& insets, base::DictionaryValue* value) {
+ DCHECK(value);
+ value->SetInteger(kInsetsTopKey, insets.top());
+ value->SetInteger(kInsetsLeftKey, insets.left());
+ value->SetInteger(kInsetsBottomKey, insets.bottom());
+ value->SetInteger(kInsetsRightKey, insets.right());
+}
+
+// Unmarshalls the string containing CalibrationPointPairQuad and populates
+// |point_pair_quad| with the unmarshalled data.
+bool ParseTouchCalibrationStringValue(
+ const std::string& str,
+ display::TouchCalibrationData::CalibrationPointPairQuad* point_pair_quad) {
+ DCHECK(point_pair_quad);
+ int x = 0, y = 0;
+ std::vector<std::string> parts = base::SplitString(
+ str, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ size_t total = point_pair_quad->size();
+ gfx::Point display_point, touch_point;
+ for (std::size_t row = 0; row < total; row++) {
+ if (!base::StringToInt(parts[row * total], &x) ||
+ !base::StringToInt(parts[row * total + 1], &y)) {
+ return false;
+ }
+ display_point.SetPoint(x, y);
+
+ if (!base::StringToInt(parts[row * total + 2], &x) ||
+ !base::StringToInt(parts[row * total + 3], &y)) {
+ return false;
+ }
+ touch_point.SetPoint(x, y);
+
+ (*point_pair_quad)[row] = std::make_pair(display_point, touch_point);
+ }
+ return true;
+}
+
+// Retrieves touch calibration associated data from the dictionary and stores
+// it in an instance of TouchCalibrationData struct.
+bool ValueToTouchData(const base::DictionaryValue& value,
+ display::TouchCalibrationData* touch_calibration_data) {
+ display::TouchCalibrationData::CalibrationPointPairQuad* point_pair_quad =
+ &(touch_calibration_data->point_pairs);
+
+ std::string str;
+ if (!value.GetString(kTouchCalibrationPointPairs, &str))
+ return false;
+
+ if (!ParseTouchCalibrationStringValue(str, point_pair_quad))
+ return false;
+
+ int width, height;
+ if (!value.GetInteger(kTouchCalibrationWidth, &width) ||
+ !value.GetInteger(kTouchCalibrationHeight, &height)) {
+ return false;
+ }
+ touch_calibration_data->bounds = gfx::Size(width, height);
+ return true;
+}
+
+// Stores the touch calibration data into the dictionary.
+void TouchDataToValue(
+ const display::TouchCalibrationData& touch_calibration_data,
+ base::DictionaryValue* value) {
+ DCHECK(value);
+ std::string str;
+ for (std::size_t row = 0; row < touch_calibration_data.point_pairs.size();
+ row++) {
+ str +=
+ base::IntToString(touch_calibration_data.point_pairs[row].first.x()) +
+ " ";
+ str +=
+ base::IntToString(touch_calibration_data.point_pairs[row].first.y()) +
+ " ";
+ str +=
+ base::IntToString(touch_calibration_data.point_pairs[row].second.x()) +
+ " ";
+ str +=
+ base::IntToString(touch_calibration_data.point_pairs[row].second.y());
+ if (row != touch_calibration_data.point_pairs.size() - 1)
+ str += " ";
+ }
+ value->SetString(kTouchCalibrationPointPairs, str);
+ value->SetInteger(kTouchCalibrationWidth,
+ touch_calibration_data.bounds.width());
+ value->SetInteger(kTouchCalibrationHeight,
+ touch_calibration_data.bounds.height());
+}
+
+std::string ColorProfileToString(display::ColorCalibrationProfile profile) {
+ switch (profile) {
+ case display::COLOR_PROFILE_STANDARD:
+ return "standard";
+ case display::COLOR_PROFILE_DYNAMIC:
+ return "dynamic";
+ case display::COLOR_PROFILE_MOVIE:
+ return "movie";
+ case display::COLOR_PROFILE_READING:
+ return "reading";
+ case display::NUM_COLOR_PROFILES:
+ break;
+ }
+ NOTREACHED();
+ return "";
+}
+
+display::ColorCalibrationProfile StringToColorProfile(
+ const std::string& value) {
+ if (value == "standard")
+ return display::COLOR_PROFILE_STANDARD;
+ else if (value == "dynamic")
+ return display::COLOR_PROFILE_DYNAMIC;
+ else if (value == "movie")
+ return display::COLOR_PROFILE_MOVIE;
+ else if (value == "reading")
+ return display::COLOR_PROFILE_READING;
+ NOTREACHED();
+ return display::COLOR_PROFILE_STANDARD;
+}
+
+// Returns true id the current user can write display preferences to
+// Local State.
+bool UserCanSaveDisplayPreference() {
+ user_manager::UserManager* user_manager = user_manager::UserManager::Get();
+ return user_manager->IsUserLoggedIn() &&
+ (user_manager->IsLoggedInAsUserWithGaiaAccount() ||
+ user_manager->IsLoggedInAsSupervisedUser() ||
+ user_manager->IsLoggedInAsKioskApp());
+}
+
+void LoadDisplayLayouts(DisplayManager* display_manager,
+ preferences::PrefClientStore* pref_client_store_) {
+ // PrefService* local_state = g_browser_process->local_state();
+ PrefService* local_state = NULL;
+ display::DisplayLayoutStore* layout_store = display_manager->layout_store();
+
+ const base::DictionaryValue* layouts =
+ local_state->GetDictionary(prefs::kSecondaryDisplays);
+ for (base::DictionaryValue::Iterator it(*layouts); !it.IsAtEnd();
+ it.Advance()) {
+ std::unique_ptr<display::DisplayLayout> layout(new display::DisplayLayout);
+ if (!display::JsonToDisplayLayout(it.value(), layout.get())) {
+ LOG(WARNING) << "Invalid preference value for " << it.key();
+ continue;
+ }
+
+ if (it.key().find(",") != std::string::npos) {
+ std::vector<std::string> ids_str = base::SplitString(
+ it.key(), ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ std::vector<int64_t> ids;
+ for (std::string id_str : ids_str) {
+ int64_t id;
+ if (!base::StringToInt64(id_str, &id))
+ continue;
+ ids.push_back(id);
+ }
+ display::DisplayIdList list =
+ display::GenerateDisplayIdList(ids.begin(), ids.end());
+ layout_store->RegisterLayoutForDisplayIdList(list, std::move(layout));
+ }
+ }
+}
+
+void LoadDisplayProperties(DisplayManager* display_manager,
+ preferences::PrefClientStore* pref_client_store_) {
+ // PrefService* local_state = g_browser_process->local_state();
+ PrefService* local_state = NULL;
+ const base::DictionaryValue* properties =
+ local_state->GetDictionary(prefs::kDisplayProperties);
+ for (base::DictionaryValue::Iterator it(*properties); !it.IsAtEnd();
+ it.Advance()) {
+ const base::DictionaryValue* dict_value = nullptr;
+ if (!it.value().GetAsDictionary(&dict_value) || dict_value == nullptr)
+ continue;
+ int64_t id = display::kInvalidDisplayId;
+ if (!base::StringToInt64(it.key(), &id) ||
+ id == display::kInvalidDisplayId) {
+ continue;
+ }
+ display::Display::Rotation rotation = display::Display::ROTATE_0;
+ float ui_scale = 1.0f;
+ const gfx::Insets* insets_to_set = nullptr;
+
+ int rotation_value = 0;
+ if (dict_value->GetInteger("rotation", &rotation_value)) {
+ rotation = static_cast<display::Display::Rotation>(rotation_value);
+ }
+ int ui_scale_value = 0;
+ if (dict_value->GetInteger("ui-scale", &ui_scale_value))
+ ui_scale = static_cast<float>(ui_scale_value) / 1000.0f;
+
+ int width = 0, height = 0;
+ dict_value->GetInteger("width", &width);
+ dict_value->GetInteger("height", &height);
+ gfx::Size resolution_in_pixels(width, height);
+
+ float device_scale_factor = 1.0;
+ int dsf_value = 0;
+ if (dict_value->GetInteger("device-scale-factor", &dsf_value))
+ device_scale_factor = static_cast<float>(dsf_value) / 1000.0f;
+
+ gfx::Insets insets;
+ if (ValueToInsets(*dict_value, &insets))
+ insets_to_set = &insets;
+
+ display::TouchCalibrationData calibration_data;
+ display::TouchCalibrationData* calibration_data_to_set = nullptr;
+ if (ValueToTouchData(*dict_value, &calibration_data))
+ calibration_data_to_set = &calibration_data;
+
+ display::ColorCalibrationProfile color_profile =
+ display::COLOR_PROFILE_STANDARD;
+ std::string color_profile_name;
+ if (dict_value->GetString("color_profile_name", &color_profile_name))
+ color_profile = StringToColorProfile(color_profile_name);
+ display_manager->RegisterDisplayProperty(
+ id, rotation, ui_scale, insets_to_set, resolution_in_pixels,
+ device_scale_factor, color_profile, calibration_data_to_set);
+ }
+}
+
+void LoadDisplayRotationState(
+ DisplayManager* display_manager,
+ preferences::PrefClientStore* pref_client_store_) {
+ // PrefService* local_state = g_browser_process->local_state();
+ PrefService* local_state = NULL;
+ const base::DictionaryValue* properties =
+ local_state->GetDictionary(prefs::kDisplayRotationLock);
+
+ bool rotation_lock = false;
+ if (!properties->GetBoolean("lock", &rotation_lock))
+ return;
+
+ int rotation = display::Display::ROTATE_0;
+ if (!properties->GetInteger("orientation", &rotation))
+ return;
+
+ display_manager->RegisterDisplayRotationProperties(
+ rotation_lock, static_cast<display::Display::Rotation>(rotation));
+}
+
+void StoreDisplayLayoutPref(const display::DisplayIdList& list,
+ const display::DisplayLayout& display_layout) {
+ std::string name = display::DisplayIdListToString(list);
+
+ // PrefService* local_state = g_browser_process->local_state();
+ PrefService* local_state = NULL;
+ DictionaryPrefUpdate update(local_state, prefs::kSecondaryDisplays);
+ base::DictionaryValue* pref_data = update.Get();
+ std::unique_ptr<base::Value> layout_value(new base::DictionaryValue());
+ if (pref_data->HasKey(name)) {
+ base::Value* value = nullptr;
+ if (pref_data->Get(name, &value) && value != nullptr)
+ layout_value.reset(value->DeepCopy());
+ }
+ if (display::DisplayLayoutToJson(display_layout, layout_value.get()))
+ pref_data->Set(name, layout_value.release());
+}
+
+void StoreCurrentDisplayLayoutPrefs(DisplayManager* display_manager) {
+ if (!UserCanSaveDisplayPreference() ||
+ display_manager->num_connected_displays() < 2) {
+ return;
+ }
+
+ display::DisplayIdList list = display_manager->GetCurrentDisplayIdList();
+ const display::DisplayLayout& display_layout =
+ display_manager->layout_store()->GetRegisteredDisplayLayout(list);
+ StoreDisplayLayoutPref(list, display_layout);
+}
+
+void StoreCurrentDisplayProperties(DisplayManager* display_manager) {
+ // PrefService* local_state = g_browser_process->local_state();
+ PrefService* local_state = NULL;
+
+ DictionaryPrefUpdate update(local_state, prefs::kDisplayProperties);
+ base::DictionaryValue* pref_data = update.Get();
+
+ size_t num = display_manager->GetNumDisplays();
+ for (size_t i = 0; i < num; ++i) {
+ const display::Display& display = display_manager->GetDisplayAt(i);
+ int64_t id = display.id();
+ display::ManagedDisplayInfo info = display_manager->GetDisplayInfo(id);
+
+ std::unique_ptr<base::DictionaryValue> property_value(
+ new base::DictionaryValue());
+ // Don't save the display preference in unified mode because its
+ // size and modes can change depending on the combination of displays.
+ if (display_manager->IsInUnifiedMode())
+ continue;
+ property_value->SetInteger("rotation",
+ static_cast<int>(info.GetRotation(
+ display::Display::ROTATION_SOURCE_USER)));
+ property_value->SetInteger(
+ "ui-scale", static_cast<int>(info.configured_ui_scale() * 1000));
+
+ scoped_refptr<display::ManagedDisplayMode> mode =
+ display_manager->GetSelectedModeForDisplayId(id);
+ if (!display.IsInternal() && mode && !mode->native()) {
+ property_value->SetInteger("width", mode->size().width());
+ property_value->SetInteger("height", mode->size().height());
+ property_value->SetInteger(
+ "device-scale-factor",
+ static_cast<int>(mode->device_scale_factor() * 1000));
+ }
+ if (!info.overscan_insets_in_dip().IsEmpty())
+ InsetsToValue(info.overscan_insets_in_dip(), property_value.get());
+ if (info.color_profile() != display::COLOR_PROFILE_STANDARD) {
+ property_value->SetString("color_profile_name",
+ ColorProfileToString(info.color_profile()));
+ }
+ if (info.has_touch_calibration_data())
+ TouchDataToValue(info.GetTouchCalibrationData(), property_value.get());
+ pref_data->Set(base::Int64ToString(id), property_value.release());
+ }
+}
+
+typedef std::map<chromeos::DisplayPowerState, std::string>
+ DisplayPowerStateToStringMap;
+
+const DisplayPowerStateToStringMap* GetDisplayPowerStateToStringMap() {
+ // Don't save or retore ALL_OFF state. crbug.com/318456.
+ static const DisplayPowerStateToStringMap* map = display::CreateToStringMap(
+ chromeos::DISPLAY_POWER_ALL_ON, "all_on",
+ chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON,
+ "internal_off_external_on",
+ chromeos::DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF,
+ "internal_on_external_off");
+ return map;
+}
+
+bool GetDisplayPowerStateFromString(const base::StringPiece& state,
+ chromeos::DisplayPowerState* field) {
+ if (display::ReverseFind(GetDisplayPowerStateToStringMap(), state, field))
+ return true;
+ LOG(ERROR) << "Invalid display power state value:" << state;
+ return false;
+}
+
+void StoreDisplayPowerState(chromeos::DisplayPowerState power_state) {
+ const DisplayPowerStateToStringMap* map = GetDisplayPowerStateToStringMap();
+ DisplayPowerStateToStringMap::const_iterator iter = map->find(power_state);
+ if (iter != map->end()) {
+ // PrefService* local_state = g_browser_process->local_state();
+ PrefService* local_state = NULL;
+ local_state->SetString(prefs::kDisplayPowerState, iter->second);
+ }
+}
+
+void StoreCurrentDisplayPowerState(DisplayConfigurator* display_configurator) {
+ StoreDisplayPowerState(display_configurator->requested_power_state());
+}
+
+void StoreDisplayRotationPrefs(DisplayManager* display_manager,
+ bool rotation_lock) {
+ if (!display::Display::HasInternalDisplay())
+ return;
+
+ // PrefService* local_state = g_browser_process->local_state();
+ PrefService* local_state = NULL;
+ DictionaryPrefUpdate update(local_state, prefs::kDisplayRotationLock);
+ base::DictionaryValue* pref_data = update.Get();
+ pref_data->SetBoolean("lock", rotation_lock);
+ display::Display::Rotation rotation =
+ display_manager->GetDisplayInfo(display::Display::InternalDisplayId())
+ .GetRotation(display::Display::ROTATION_SOURCE_ACCELEROMETER);
+ pref_data->SetInteger("orientation", static_cast<int>(rotation));
+}
+
+void StoreCurrentDisplayRotationLockPrefs(DisplayManager* display_manager) {
+ bool rotation_lock =
+ display_manager->registered_internal_display_rotation_lock();
+ StoreDisplayRotationPrefs(display_manager, rotation_lock);
+}
+
+} // namespace
+
+void RegisterDisplayLocalStatePrefs(PrefRegistrySimple* registry) {
+ // Per-display preference.
+ registry->RegisterDictionaryPref(prefs::kSecondaryDisplays);
+ registry->RegisterDictionaryPref(prefs::kDisplayProperties);
+ DisplayPowerStateToStringMap::const_iterator iter =
+ GetDisplayPowerStateToStringMap()->find(chromeos::DISPLAY_POWER_ALL_ON);
+ registry->RegisterStringPref(prefs::kDisplayPowerState, iter->second);
+ registry->RegisterDictionaryPref(prefs::kDisplayRotationLock);
+}
+
+void StoreDisplayPrefs(DisplayConfigurator* display_configurator,
+ DisplayManager* display_manager) {
+ // Stores the power state regardless of the login status, because the power
+ // state respects to the current status (close/open) of the lid which can be
+ // changed in any situation. See crbug.com/285360
+ StoreCurrentDisplayPowerState(display_configurator);
+ StoreCurrentDisplayRotationLockPrefs(display_manager);
+
+ // Do not store prefs when the confirmation dialog is shown.
+ if (!UserCanSaveDisplayPreference() ||
+ !ash::Shell::GetInstance()->ShouldSaveDisplaySettings()) {
+ return;
+ }
+
+ StoreCurrentDisplayLayoutPrefs(display_manager);
+ StoreCurrentDisplayProperties(display_manager);
+}
+
+void LoadDisplayPreferences(bool first_run_after_boot,
+ DisplayConfigurator* display_configurator,
+ DisplayManager* display_manager,
+ preferences::PrefClientStore* pref_client_store_) {
+ // void LoadDisplayPreferences(bool first_run_after_boot, DisplayConfigurator*
+ // display_configurator, DisplayManager* display_manager) {
+ LoadDisplayLayouts(display_manager, pref_client_store_);
+ LoadDisplayProperties(display_manager, pref_client_store_);
+ LoadDisplayRotationState(display_manager, pref_client_store_);
+ if (!first_run_after_boot) {
+ // PrefService* local_state = g_browser_process->local_state();
+ PrefService* local_state = NULL;
+ // Restore DisplayPowerState:
+ std::string value = local_state->GetString(prefs::kDisplayPowerState);
+ chromeos::DisplayPowerState power_state;
+ if (GetDisplayPowerStateFromString(value, &power_state)) {
+ display_configurator->SetInitialDisplayPower(power_state);
+ }
+ }
+}
+
+// Stores the display layout for given display pairs.
+void StoreDisplayLayoutPrefForTest(const display::DisplayIdList& list,
+ const display::DisplayLayout& layout) {
+ StoreDisplayLayoutPref(list, layout);
+}
+
+// Stores the given |power_state|.
+void StoreDisplayPowerStateForTest(chromeos::DisplayPowerState power_state) {
+ StoreDisplayPowerState(power_state);
+}
+
+bool ParseTouchCalibrationStringForTest(
+ const std::string& str,
+ display::TouchCalibrationData::CalibrationPointPairQuad* point_pair_quad) {
+ return ParseTouchCalibrationStringValue(str, point_pair_quad);
+}
+
+} // namespace chromeos

Powered by Google App Engine
This is Rietveld 408576698