| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "ui/gfx/display_layout.h" | 5 #include "ui/gfx/display_layout.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <sstream> | 8 #include <sstream> |
| 9 | 9 |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
| 12 #include "base/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
| 13 #include "base/values.h" | 13 #include "base/values.h" |
| 14 #include "ui/gfx/display.h" | 14 #include "ui/gfx/display.h" |
| 15 #include "ui/gfx/geometry/insets.h" |
| 15 | 16 |
| 16 namespace gfx { | 17 namespace gfx { |
| 17 namespace { | 18 namespace { |
| 18 | 19 |
| 19 // DisplayPlacement Positions | 20 // DisplayPlacement Positions |
| 20 const char kTop[] = "top"; | 21 const char kTop[] = "top"; |
| 21 const char kRight[] = "right"; | 22 const char kRight[] = "right"; |
| 22 const char kBottom[] = "bottom"; | 23 const char kBottom[] = "bottom"; |
| 23 const char kLeft[] = "left"; | 24 const char kLeft[] = "left"; |
| 24 const char kUnknown[] = "unknown"; | 25 const char kUnknown[] = "unknown"; |
| 25 | 26 |
| 26 // The maximum value for 'offset' in DisplayLayout in case of outliers. Need | 27 // The maximum value for 'offset' in DisplayLayout in case of outliers. Need |
| 27 // to change this value in case to support even larger displays. | 28 // to change this value in case to support even larger displays. |
| 28 const int kMaxValidOffset = 10000; | 29 const int kMaxValidOffset = 10000; |
| 29 | 30 |
| 30 bool IsIdInList(int64_t id, const DisplayIdList& list) { | 31 bool IsIdInList(int64_t id, const DisplayIdList& list) { |
| 31 const auto iter = | 32 const auto iter = |
| 32 std::find_if(list.begin(), list.end(), | 33 std::find_if(list.begin(), list.end(), |
| 33 [id](int64_t display_id) { return display_id == id; }); | 34 [id](int64_t display_id) { return display_id == id; }); |
| 34 return iter != list.end(); | 35 return iter != list.end(); |
| 35 } | 36 } |
| 36 | 37 |
| 38 gfx::Display* FindDisplayById(DisplayList* display_list, int64_t id) { |
| 39 auto iter = std::find_if( |
| 40 display_list->begin(), display_list->end(), |
| 41 [id](const gfx::Display& display) { return display.id() == id; }); |
| 42 return &(*iter); |
| 43 } |
| 44 |
| 37 } // namespace | 45 } // namespace |
| 38 | 46 |
| 39 //////////////////////////////////////////////////////////////////////////////// | 47 //////////////////////////////////////////////////////////////////////////////// |
| 40 // DisplayPlacement | 48 // DisplayPlacement |
| 41 | 49 |
| 42 DisplayPlacement::DisplayPlacement() | 50 DisplayPlacement::DisplayPlacement() |
| 43 : display_id(gfx::Display::kInvalidDisplayID), | 51 : DisplayPlacement(gfx::Display::kInvalidDisplayID, |
| 44 parent_display_id(gfx::Display::kInvalidDisplayID), | 52 gfx::Display::kInvalidDisplayID, |
| 45 position(DisplayPlacement::RIGHT), | 53 DisplayPlacement::RIGHT, |
| 46 offset(0) {} | 54 0, |
| 47 | 55 DisplayPlacement::TOP_LEFT) {} |
| 48 DisplayPlacement::DisplayPlacement(const DisplayPlacement& placement) | |
| 49 : display_id(placement.display_id), | |
| 50 parent_display_id(placement.parent_display_id), | |
| 51 position(placement.position), | |
| 52 offset(placement.offset) {} | |
| 53 | 56 |
| 54 DisplayPlacement::DisplayPlacement(Position pos, int offset) | 57 DisplayPlacement::DisplayPlacement(Position pos, int offset) |
| 55 : display_id(gfx::Display::kInvalidDisplayID), | 58 : DisplayPlacement(gfx::Display::kInvalidDisplayID, |
| 56 parent_display_id(gfx::Display::kInvalidDisplayID), | 59 gfx::Display::kInvalidDisplayID, |
| 57 position(pos), | 60 position, |
| 58 offset(offset) { | 61 offset, |
| 62 DisplayPlacement::TOP_LEFT) {} |
| 63 |
| 64 DisplayPlacement::DisplayPlacement(Position position, |
| 65 int offset, |
| 66 OffsetReference offset_reference) |
| 67 : DisplayPlacement(gfx::Display::kInvalidDisplayID, |
| 68 gfx::Display::kInvalidDisplayID, |
| 69 position, |
| 70 offset, |
| 71 offset_reference) {} |
| 72 |
| 73 DisplayPlacement::DisplayPlacement(int64_t display_id, |
| 74 int64_t parent_display_id, |
| 75 Position position, |
| 76 int offset, |
| 77 OffsetReference offset_reference) |
| 78 : display_id(display_id), |
| 79 parent_display_id(parent_display_id), |
| 80 position(position), |
| 81 offset(offset), |
| 82 offset_reference(offset_reference) { |
| 59 DCHECK_LE(TOP, position); | 83 DCHECK_LE(TOP, position); |
| 60 DCHECK_GE(LEFT, position); | 84 DCHECK_GE(LEFT, position); |
| 61 // Set the default value to |position| in case position is invalid. DCHECKs | 85 // Set the default value to |position| in case position is invalid. DCHECKs |
| 62 // above doesn't stop in Release builds. | 86 // above doesn't stop in Release builds. |
| 63 if (TOP > position || LEFT < position) | 87 if (TOP > position || LEFT < position) |
| 64 this->position = RIGHT; | 88 this->position = RIGHT; |
| 65 | 89 |
| 66 DCHECK_GE(kMaxValidOffset, abs(offset)); | 90 DCHECK_GE(kMaxValidOffset, abs(offset)); |
| 67 } | 91 } |
| 68 | 92 |
| 93 DisplayPlacement::DisplayPlacement(const DisplayPlacement& placement) |
| 94 : display_id(placement.display_id), |
| 95 parent_display_id(placement.parent_display_id), |
| 96 position(placement.position), |
| 97 offset(placement.offset), |
| 98 offset_reference(placement.offset_reference) {} |
| 99 |
| 69 DisplayPlacement& DisplayPlacement::Swap() { | 100 DisplayPlacement& DisplayPlacement::Swap() { |
| 70 switch (position) { | 101 switch (position) { |
| 71 case TOP: | 102 case TOP: |
| 72 position = BOTTOM; | 103 position = BOTTOM; |
| 73 break; | 104 break; |
| 74 case BOTTOM: | 105 case BOTTOM: |
| 75 position = TOP; | 106 position = TOP; |
| 76 break; | 107 break; |
| 77 case RIGHT: | 108 case RIGHT: |
| 78 position = LEFT; | 109 position = LEFT; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 //////////////////////////////////////////////////////////////////////////////// | 174 //////////////////////////////////////////////////////////////////////////////// |
| 144 // DisplayLayout | 175 // DisplayLayout |
| 145 | 176 |
| 146 DisplayLayout::DisplayLayout() | 177 DisplayLayout::DisplayLayout() |
| 147 : mirrored(false), | 178 : mirrored(false), |
| 148 default_unified(true), | 179 default_unified(true), |
| 149 primary_id(gfx::Display::kInvalidDisplayID) {} | 180 primary_id(gfx::Display::kInvalidDisplayID) {} |
| 150 | 181 |
| 151 DisplayLayout::~DisplayLayout() {} | 182 DisplayLayout::~DisplayLayout() {} |
| 152 | 183 |
| 184 void DisplayLayout::ApplyToDisplayList( |
| 185 DisplayList* display_list, |
| 186 std::vector<int64_t>* updated_ids, |
| 187 int minimum_offset_overlap) const { |
| 188 // Layout from primary, then dependent displays. |
| 189 std::set<int64_t> parents; |
| 190 parents.insert(primary_id); |
| 191 while (parents.size()) { |
| 192 int64_t parent_id = *parents.begin(); |
| 193 parents.erase(parent_id); |
| 194 for (const DisplayPlacement* placement : placement_list) { |
| 195 if (placement->parent_display_id == parent_id) { |
| 196 if (ApplyDisplayPlacement(*placement, |
| 197 display_list, |
| 198 minimum_offset_overlap) && |
| 199 updated_ids) |
| 200 updated_ids->push_back(placement->display_id); |
| 201 parents.insert(placement->display_id); |
| 202 } |
| 203 } |
| 204 } |
| 205 } |
| 206 |
| 207 bool DisplayLayout::ApplyDisplayPlacement( |
| 208 const DisplayPlacement& placement, |
| 209 DisplayList* display_list, |
| 210 int minimum_offset_overlap) const { |
| 211 const gfx::Display& parent_display = |
| 212 *FindDisplayById(display_list, placement.parent_display_id); |
| 213 DCHECK(parent_display.is_valid()); |
| 214 gfx::Display* target_display = |
| 215 FindDisplayById(display_list, placement.display_id); |
| 216 gfx::Rect old_bounds(target_display->bounds()); |
| 217 DCHECK(target_display); |
| 218 |
| 219 const gfx::Rect& parent_bounds = parent_display.bounds(); |
| 220 const gfx::Rect& target_bounds = target_display->bounds(); |
| 221 gfx::Point new_target_origin = parent_bounds.origin(); |
| 222 |
| 223 DisplayPlacement::Position position = placement.position; |
| 224 |
| 225 // Ignore the offset in case the target display doesn't share edges with |
| 226 // the parent display. |
| 227 int offset = placement.offset; |
| 228 if (position == DisplayPlacement::TOP || |
| 229 position == DisplayPlacement::BOTTOM) { |
| 230 if (placement.offset_reference == DisplayPlacement::BOTTOM_RIGHT) |
| 231 offset += parent_bounds.width() - target_bounds.width(); |
| 232 |
| 233 offset = std::min( |
| 234 offset, parent_bounds.width() - minimum_offset_overlap); |
| 235 offset = std::max( |
| 236 offset, -target_bounds.width() + minimum_offset_overlap); |
| 237 } else { |
| 238 if (placement.offset_reference == DisplayPlacement::BOTTOM_RIGHT) |
| 239 offset += parent_bounds.height() - target_bounds.height(); |
| 240 |
| 241 offset = std::min( |
| 242 offset, parent_bounds.height() - minimum_offset_overlap); |
| 243 offset = std::max( |
| 244 offset, -target_bounds.height() + minimum_offset_overlap); |
| 245 } |
| 246 switch (position) { |
| 247 case DisplayPlacement::TOP: |
| 248 new_target_origin.Offset(offset, -target_bounds.height()); |
| 249 break; |
| 250 case DisplayPlacement::RIGHT: |
| 251 new_target_origin.Offset(parent_bounds.width(), offset); |
| 252 break; |
| 253 case DisplayPlacement::BOTTOM: |
| 254 new_target_origin.Offset(offset, parent_bounds.height()); |
| 255 break; |
| 256 case DisplayPlacement::LEFT: |
| 257 new_target_origin.Offset(-target_bounds.width(), offset); |
| 258 break; |
| 259 } |
| 260 |
| 261 gfx::Insets insets = target_display->GetWorkAreaInsets(); |
| 262 target_display->set_bounds( |
| 263 gfx::Rect(new_target_origin, target_bounds.size())); |
| 264 target_display->UpdateWorkAreaFromInsets(insets); |
| 265 |
| 266 return old_bounds != target_display->bounds(); |
| 267 } |
| 268 |
| 153 // static | 269 // static |
| 154 bool DisplayLayout::Validate(const DisplayIdList& list, | 270 bool DisplayLayout::Validate(const DisplayIdList& list, |
| 155 const DisplayLayout& layout) { | 271 const DisplayLayout& layout) { |
| 156 // The primary display should be in the list. | 272 // The primary display should be in the list. |
| 157 DCHECK(IsIdInList(layout.primary_id, list)); | 273 DCHECK(IsIdInList(layout.primary_id, list)); |
| 158 | 274 |
| 159 // Unified mode, or mirror mode switched from unified mode, | 275 // Unified mode, or mirror mode switched from unified mode, |
| 160 // may not have the placement yet. | 276 // may not have the placement yet. |
| 161 if (layout.placement_list.size() == 0u) | 277 if (layout.placement_list.size() == 0u) |
| 162 return true; | 278 return true; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 248 int64_t display_id) const { | 364 int64_t display_id) const { |
| 249 const auto iter = | 365 const auto iter = |
| 250 std::find_if(placement_list.begin(), placement_list.end(), | 366 std::find_if(placement_list.begin(), placement_list.end(), |
| 251 [display_id](const DisplayPlacement* placement) { | 367 [display_id](const DisplayPlacement* placement) { |
| 252 return placement->display_id == display_id; | 368 return placement->display_id == display_id; |
| 253 }); | 369 }); |
| 254 return (iter == placement_list.end()) ? nullptr : *iter; | 370 return (iter == placement_list.end()) ? nullptr : *iter; |
| 255 } | 371 } |
| 256 | 372 |
| 257 } // namespace gfx | 373 } // namespace gfx |
| OLD | NEW |