| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 "ash/display/display_layout.h" | 5 #include "ash/display/display_layout.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <sstream> | 8 #include <sstream> |
| 9 | 9 |
| 10 #include "ash/ash_switches.h" | 10 #include "ash/ash_switches.h" |
| 11 #include "ash/display/display_pref_util.h" | 11 #include "ash/display/display_pref_util.h" |
| 12 #include "ash/shell.h" | 12 #include "ash/shell.h" |
| 13 #include "base/json/json_value_converter.h" | |
| 14 #include "base/logging.h" | 13 #include "base/logging.h" |
| 15 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 16 #include "base/strings/string_piece.h" | |
| 17 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
| 18 #include "base/values.h" | 16 #include "base/values.h" |
| 19 #include "ui/gfx/display.h" | 17 #include "ui/gfx/display.h" |
| 20 | 18 |
| 21 namespace ash { | 19 namespace ash { |
| 22 namespace { | 20 namespace { |
| 23 | 21 |
| 22 // DisplayPlacement Positions |
| 23 const char kTop[] = "top"; |
| 24 const char kRight[] = "right"; |
| 25 const char kBottom[] = "bottom"; |
| 26 const char kLeft[] = "left"; |
| 27 const char kUnknown[] = "unknown"; |
| 28 |
| 24 // The maximum value for 'offset' in DisplayLayout in case of outliers. Need | 29 // The maximum value for 'offset' in DisplayLayout in case of outliers. Need |
| 25 // to change this value in case to support even larger displays. | 30 // to change this value in case to support even larger displays. |
| 26 const int kMaxValidOffset = 10000; | 31 const int kMaxValidOffset = 10000; |
| 27 | 32 |
| 28 // Persistent key names | |
| 29 const char kMirroredKey[] = "mirrored"; | |
| 30 const char kDefaultUnifiedKey[] = "default_unified"; | |
| 31 const char kPrimaryIdKey[] = "primary-id"; | |
| 32 const char kDisplayPlacementKey[] = "display_placement"; | |
| 33 | |
| 34 // DisplayPlacement | |
| 35 const char kPositionKey[] = "position"; | |
| 36 const char kOffsetKey[] = "offset"; | |
| 37 const char kDisplayPlacementDisplayIdKey[] = "display_id"; | |
| 38 const char kDisplayPlacementParentDisplayIdKey[] = "parent_display_id"; | |
| 39 | |
| 40 using PositionToStringMap = std::map<DisplayPlacement::Position, std::string>; | |
| 41 using DisplayPlacementMap = std::unordered_map<int64_t, DisplayPlacement>; | |
| 42 | |
| 43 const PositionToStringMap* GetPositionToStringMap() { | |
| 44 static const PositionToStringMap* map = CreateToStringMap( | |
| 45 DisplayPlacement::TOP, "top", DisplayPlacement::BOTTOM, "bottom", | |
| 46 DisplayPlacement::RIGHT, "right", DisplayPlacement::LEFT, "left"); | |
| 47 return map; | |
| 48 } | |
| 49 | |
| 50 std::string ToPositionString(DisplayPlacement::Position position) { | |
| 51 const PositionToStringMap* map = GetPositionToStringMap(); | |
| 52 PositionToStringMap::const_iterator iter = map->find(position); | |
| 53 return iter != map->end() ? iter->second : std::string("unknown"); | |
| 54 } | |
| 55 | |
| 56 bool GetPositionFromString(const base::StringPiece& position, | |
| 57 DisplayPlacement::Position* field) { | |
| 58 if (ReverseFind(GetPositionToStringMap(), position, field)) | |
| 59 return true; | |
| 60 LOG(ERROR) << "Invalid position value:" << position; | |
| 61 return false; | |
| 62 } | |
| 63 | |
| 64 bool GetDisplayIdFromString(const base::StringPiece& position, int64_t* field) { | |
| 65 return base::StringToInt64(position, field); | |
| 66 } | |
| 67 | |
| 68 bool IsIdInList(int64_t id, const DisplayIdList& list) { | 33 bool IsIdInList(int64_t id, const DisplayIdList& list) { |
| 69 const auto iter = | 34 const auto iter = |
| 70 std::find_if(list.begin(), list.end(), | 35 std::find_if(list.begin(), list.end(), |
| 71 [id](int64_t display_id) { return display_id == id; }); | 36 [id](int64_t display_id) { return display_id == id; }); |
| 72 return iter != list.end(); | 37 return iter != list.end(); |
| 73 } | 38 } |
| 74 | 39 |
| 75 } // namespace | 40 } // namespace |
| 76 | 41 |
| 77 //////////////////////////////////////////////////////////////////////////////// | 42 //////////////////////////////////////////////////////////////////////////////// |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 std::swap(display_id, parent_display_id); | 88 std::swap(display_id, parent_display_id); |
| 124 return *this; | 89 return *this; |
| 125 } | 90 } |
| 126 | 91 |
| 127 std::string DisplayPlacement::ToString() const { | 92 std::string DisplayPlacement::ToString() const { |
| 128 std::stringstream s; | 93 std::stringstream s; |
| 129 if (display_id != gfx::Display::kInvalidDisplayID) | 94 if (display_id != gfx::Display::kInvalidDisplayID) |
| 130 s << "id=" << display_id << ", "; | 95 s << "id=" << display_id << ", "; |
| 131 if (parent_display_id != gfx::Display::kInvalidDisplayID) | 96 if (parent_display_id != gfx::Display::kInvalidDisplayID) |
| 132 s << "parent=" << parent_display_id << ", "; | 97 s << "parent=" << parent_display_id << ", "; |
| 133 s << ToPositionString(position) << ", "; | 98 s << PositionToString(position) << ", "; |
| 134 s << offset; | 99 s << offset; |
| 135 return s.str(); | 100 return s.str(); |
| 136 } | 101 } |
| 137 | 102 |
| 138 // static | 103 // static |
| 139 void DisplayPlacement::RegisterJSONConverter( | 104 std::string DisplayPlacement::PositionToString(Position position) { |
| 140 base::JSONValueConverter<DisplayPlacement>* converter) { | 105 switch (position) { |
| 141 converter->RegisterIntField(kOffsetKey, &DisplayPlacement::offset); | 106 case TOP: |
| 142 converter->RegisterCustomField<DisplayPlacement::Position>( | 107 return kTop; |
| 143 kPositionKey, &DisplayPlacement::position, &GetPositionFromString); | 108 case RIGHT: |
| 144 converter->RegisterCustomField<int64_t>(kDisplayPlacementDisplayIdKey, | 109 return kRight; |
| 145 &DisplayPlacement::display_id, | 110 case BOTTOM: |
| 146 &GetDisplayIdFromString); | 111 return kBottom; |
| 147 converter->RegisterCustomField<int64_t>(kDisplayPlacementParentDisplayIdKey, | 112 case LEFT: |
| 148 &DisplayPlacement::parent_display_id, | 113 return kLeft; |
| 149 &GetDisplayIdFromString); | 114 } |
| 115 return kUnknown; |
| 116 } |
| 117 |
| 118 // static |
| 119 bool DisplayPlacement::StringToPosition(const base::StringPiece& string, |
| 120 Position* position) { |
| 121 if (string == kTop) { |
| 122 *position = TOP; |
| 123 return true; |
| 124 } |
| 125 |
| 126 if (string == kRight) { |
| 127 *position = RIGHT; |
| 128 return true; |
| 129 } |
| 130 |
| 131 if (string == kBottom) { |
| 132 *position = BOTTOM; |
| 133 return true; |
| 134 } |
| 135 |
| 136 if (string == kLeft) { |
| 137 *position = LEFT; |
| 138 return true; |
| 139 } |
| 140 |
| 141 LOG(ERROR) << "Invalid position value:" << string; |
| 142 |
| 143 return false; |
| 150 } | 144 } |
| 151 | 145 |
| 152 //////////////////////////////////////////////////////////////////////////////// | 146 //////////////////////////////////////////////////////////////////////////////// |
| 153 // DisplayLayout | 147 // DisplayLayout |
| 154 | 148 |
| 155 DisplayLayout::DisplayLayout() | 149 DisplayLayout::DisplayLayout() |
| 156 : mirrored(false), | 150 : mirrored(false), |
| 157 default_unified(true), | 151 default_unified(true), |
| 158 primary_id(gfx::Display::kInvalidDisplayID) {} | 152 primary_id(gfx::Display::kInvalidDisplayID) {} |
| 159 | 153 |
| 160 DisplayLayout::~DisplayLayout() {} | 154 DisplayLayout::~DisplayLayout() {} |
| 161 | 155 |
| 162 // static | 156 // static |
| 163 bool DisplayLayout::ConvertFromValue(const base::Value& value, | |
| 164 DisplayLayout* layout) { | |
| 165 layout->placement_list.clear(); | |
| 166 base::JSONValueConverter<DisplayLayout> converter; | |
| 167 if (!converter.Convert(value, layout)) | |
| 168 return false; | |
| 169 if (layout->placement_list.size() != 0u) | |
| 170 return true; | |
| 171 // For compatibility with old format. | |
| 172 const base::DictionaryValue* dict_value = nullptr; | |
| 173 if (!value.GetAsDictionary(&dict_value) || dict_value == nullptr) | |
| 174 return false; | |
| 175 int offset; | |
| 176 if (dict_value->GetInteger(kOffsetKey, &offset)) { | |
| 177 DisplayPlacement::Position position; | |
| 178 std::string position_str; | |
| 179 if (!dict_value->GetString(kPositionKey, &position_str)) | |
| 180 return false; | |
| 181 GetPositionFromString(position_str, &position); | |
| 182 layout->placement_list.push_back(new DisplayPlacement(position, offset)); | |
| 183 } | |
| 184 return true; | |
| 185 } | |
| 186 | |
| 187 // static | |
| 188 bool DisplayLayout::ConvertToValue(const DisplayLayout& layout, | |
| 189 base::Value* value) { | |
| 190 base::DictionaryValue* dict_value = nullptr; | |
| 191 if (!value->GetAsDictionary(&dict_value) || dict_value == nullptr) | |
| 192 return false; | |
| 193 | |
| 194 dict_value->SetBoolean(kMirroredKey, layout.mirrored); | |
| 195 dict_value->SetBoolean(kDefaultUnifiedKey, layout.default_unified); | |
| 196 dict_value->SetString(kPrimaryIdKey, base::Int64ToString(layout.primary_id)); | |
| 197 | |
| 198 scoped_ptr<base::ListValue> placement_list(new base::ListValue); | |
| 199 for (const auto* placement : layout.placement_list) { | |
| 200 scoped_ptr<base::DictionaryValue> placement_value( | |
| 201 new base::DictionaryValue); | |
| 202 placement_value->SetString(kPositionKey, | |
| 203 ToPositionString(placement->position)); | |
| 204 placement_value->SetInteger(kOffsetKey, placement->offset); | |
| 205 placement_value->SetString(kDisplayPlacementDisplayIdKey, | |
| 206 base::Int64ToString(placement->display_id)); | |
| 207 placement_value->SetString( | |
| 208 kDisplayPlacementParentDisplayIdKey, | |
| 209 base::Int64ToString(placement->parent_display_id)); | |
| 210 placement_list->Append(std::move(placement_value)); | |
| 211 } | |
| 212 dict_value->Set(kDisplayPlacementKey, std::move(placement_list)); | |
| 213 return true; | |
| 214 } | |
| 215 | |
| 216 // static | |
| 217 void DisplayLayout::RegisterJSONConverter( | |
| 218 base::JSONValueConverter<DisplayLayout>* converter) { | |
| 219 converter->RegisterBoolField(kMirroredKey, &DisplayLayout::mirrored); | |
| 220 converter->RegisterBoolField(kDefaultUnifiedKey, | |
| 221 &DisplayLayout::default_unified); | |
| 222 converter->RegisterCustomField<int64_t>( | |
| 223 kPrimaryIdKey, &DisplayLayout::primary_id, &GetDisplayIdFromString); | |
| 224 converter->RegisterRepeatedMessage<DisplayPlacement>( | |
| 225 kDisplayPlacementKey, &DisplayLayout::placement_list); | |
| 226 } | |
| 227 | |
| 228 // static | |
| 229 bool DisplayLayout::Validate(const DisplayIdList& list, | 157 bool DisplayLayout::Validate(const DisplayIdList& list, |
| 230 const DisplayLayout& layout) { | 158 const DisplayLayout& layout) { |
| 231 // The primary display should be in the list. | 159 // The primary display should be in the list. |
| 232 DCHECK(IsIdInList(layout.primary_id, list)); | 160 DCHECK(IsIdInList(layout.primary_id, list)); |
| 233 | 161 |
| 234 // Unified mode, or mirror mode switched from unified mode, | 162 // Unified mode, or mirror mode switched from unified mode, |
| 235 // may not have the placement yet. | 163 // may not have the placement yet. |
| 236 if (layout.placement_list.size() == 0u) | 164 if (layout.placement_list.size() == 0u) |
| 237 return true; | 165 return true; |
| 238 | 166 |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 int64_t display_id) const { | 251 int64_t display_id) const { |
| 324 const auto iter = | 252 const auto iter = |
| 325 std::find_if(placement_list.begin(), placement_list.end(), | 253 std::find_if(placement_list.begin(), placement_list.end(), |
| 326 [display_id](const DisplayPlacement* placement) { | 254 [display_id](const DisplayPlacement* placement) { |
| 327 return placement->display_id == display_id; | 255 return placement->display_id == display_id; |
| 328 }); | 256 }); |
| 329 return (iter == placement_list.end()) ? nullptr : *iter; | 257 return (iter == placement_list.end()) ? nullptr : *iter; |
| 330 } | 258 } |
| 331 | 259 |
| 332 } // namespace ash | 260 } // namespace ash |
| OLD | NEW |