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

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

Issue 2540313002: Split //ui/display and create //ui/display/manager. (Closed)
Patch Set: Cleanup export header. Created 4 years 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
« no previous file with comments | « ui/display/manager/display_layout.h ('k') | ui/display/manager/display_layout_builder.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "ui/display/manager/display_layout.h"
6
7 #include <algorithm>
8 #include <set>
9 #include <sstream>
10
11 #include "base/logging.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/values.h"
15 #include "ui/display/display.h"
16 #include "ui/gfx/geometry/insets.h"
17
18 namespace display {
19 namespace {
20
21 // DisplayPlacement Positions
22 const char kTop[] = "top";
23 const char kRight[] = "right";
24 const char kBottom[] = "bottom";
25 const char kLeft[] = "left";
26 const char kUnknown[] = "unknown";
27
28 // The maximum value for 'offset' in DisplayLayout in case of outliers. Need
29 // to change this value in case to support even larger displays.
30 const int kMaxValidOffset = 10000;
31
32 bool IsIdInList(int64_t id, const DisplayIdList& list) {
33 const auto iter =
34 std::find_if(list.begin(), list.end(),
35 [id](int64_t display_id) { return display_id == id; });
36 return iter != list.end();
37 }
38
39 Display* FindDisplayById(Displays* display_list, int64_t id) {
40 auto iter =
41 std::find_if(display_list->begin(), display_list->end(),
42 [id](const Display& display) { return display.id() == id; });
43 return &(*iter);
44 }
45
46 } // namespace
47
48 ////////////////////////////////////////////////////////////////////////////////
49 // DisplayPlacement
50
51 DisplayPlacement::DisplayPlacement()
52 : DisplayPlacement(kInvalidDisplayId,
53 kInvalidDisplayId,
54 DisplayPlacement::RIGHT,
55 0,
56 DisplayPlacement::TOP_LEFT) {}
57
58 DisplayPlacement::DisplayPlacement(Position position, int offset)
59 : DisplayPlacement(kInvalidDisplayId,
60 kInvalidDisplayId,
61 position,
62 offset,
63 DisplayPlacement::TOP_LEFT) {}
64
65 DisplayPlacement::DisplayPlacement(Position position,
66 int offset,
67 OffsetReference offset_reference)
68 : DisplayPlacement(kInvalidDisplayId,
69 kInvalidDisplayId,
70 position,
71 offset,
72 offset_reference) {}
73
74 DisplayPlacement::DisplayPlacement(int64_t display_id,
75 int64_t parent_display_id,
76 Position position,
77 int offset,
78 OffsetReference offset_reference)
79 : display_id(display_id),
80 parent_display_id(parent_display_id),
81 position(position),
82 offset(offset),
83 offset_reference(offset_reference) {
84 DCHECK_LE(TOP, position);
85 DCHECK_GE(LEFT, position);
86 // Set the default value to |position| in case position is invalid. DCHECKs
87 // above doesn't stop in Release builds.
88 if (TOP > position || LEFT < position)
89 this->position = RIGHT;
90
91 DCHECK_GE(kMaxValidOffset, abs(offset));
92 }
93
94 DisplayPlacement::DisplayPlacement(const DisplayPlacement& placement)
95 : display_id(placement.display_id),
96 parent_display_id(placement.parent_display_id),
97 position(placement.position),
98 offset(placement.offset),
99 offset_reference(placement.offset_reference) {}
100
101 DisplayPlacement& DisplayPlacement::Swap() {
102 switch (position) {
103 case TOP:
104 position = BOTTOM;
105 break;
106 case BOTTOM:
107 position = TOP;
108 break;
109 case RIGHT:
110 position = LEFT;
111 break;
112 case LEFT:
113 position = RIGHT;
114 break;
115 }
116 offset = -offset;
117 std::swap(display_id, parent_display_id);
118 return *this;
119 }
120
121 std::string DisplayPlacement::ToString() const {
122 std::stringstream s;
123 if (display_id != kInvalidDisplayId)
124 s << "id=" << display_id << ", ";
125 if (parent_display_id != kInvalidDisplayId)
126 s << "parent=" << parent_display_id << ", ";
127 s << PositionToString(position) << ", ";
128 s << offset;
129 return s.str();
130 }
131
132 // static
133 std::string DisplayPlacement::PositionToString(Position position) {
134 switch (position) {
135 case TOP:
136 return kTop;
137 case RIGHT:
138 return kRight;
139 case BOTTOM:
140 return kBottom;
141 case LEFT:
142 return kLeft;
143 }
144 return kUnknown;
145 }
146
147 // static
148 bool DisplayPlacement::StringToPosition(const base::StringPiece& string,
149 Position* position) {
150 if (string == kTop) {
151 *position = TOP;
152 return true;
153 }
154
155 if (string == kRight) {
156 *position = RIGHT;
157 return true;
158 }
159
160 if (string == kBottom) {
161 *position = BOTTOM;
162 return true;
163 }
164
165 if (string == kLeft) {
166 *position = LEFT;
167 return true;
168 }
169
170 LOG(ERROR) << "Invalid position value:" << string;
171
172 return false;
173 }
174
175 ////////////////////////////////////////////////////////////////////////////////
176 // DisplayLayout
177
178 DisplayLayout::DisplayLayout()
179 : mirrored(false), default_unified(true), primary_id(kInvalidDisplayId) {}
180
181 DisplayLayout::~DisplayLayout() {}
182
183 void DisplayLayout::ApplyToDisplayList(Displays* display_list,
184 std::vector<int64_t>* updated_ids,
185 int minimum_offset_overlap) const {
186 // Layout from primary, then dependent displays.
187 std::set<int64_t> parents;
188 parents.insert(primary_id);
189 while (parents.size()) {
190 int64_t parent_id = *parents.begin();
191 parents.erase(parent_id);
192 for (const DisplayPlacement& placement : placement_list) {
193 if (placement.parent_display_id == parent_id) {
194 if (ApplyDisplayPlacement(placement,
195 display_list,
196 minimum_offset_overlap) &&
197 updated_ids) {
198 updated_ids->push_back(placement.display_id);
199 }
200 parents.insert(placement.display_id);
201 }
202 }
203 }
204 }
205
206 // static
207 bool DisplayLayout::Validate(const DisplayIdList& list,
208 const DisplayLayout& layout) {
209 // The primary display should be in the list.
210 DCHECK(IsIdInList(layout.primary_id, list));
211
212 // Unified mode, or mirror mode switched from unified mode,
213 // may not have the placement yet.
214 if (layout.placement_list.size() == 0u)
215 return true;
216
217 bool has_primary_as_parent = false;
218 int64_t prev_id = std::numeric_limits<int64_t>::min();
219 for (const auto& placement : layout.placement_list) {
220 // Placements are sorted by display_id.
221 if (prev_id >= placement.display_id) {
222 LOG(ERROR) << "PlacementList must be sorted by display_id";
223 return false;
224 }
225 prev_id = placement.display_id;
226 if (placement.display_id == kInvalidDisplayId) {
227 LOG(ERROR) << "display_id is not initialized";
228 return false;
229 }
230 if (placement.parent_display_id == kInvalidDisplayId) {
231 LOG(ERROR) << "display_parent_id is not initialized";
232 return false;
233 }
234 if (placement.display_id == placement.parent_display_id) {
235 LOG(ERROR) << "display_id must not be same as parent_display_id";
236 return false;
237 }
238 if (!IsIdInList(placement.display_id, list)) {
239 LOG(ERROR) << "display_id is not in the id list:" << placement.ToString();
240 return false;
241 }
242
243 if (!IsIdInList(placement.parent_display_id, list)) {
244 LOG(ERROR) << "parent_display_id is not in the id list:"
245 << placement.ToString();
246 return false;
247 }
248 has_primary_as_parent |= layout.primary_id == placement.parent_display_id;
249 }
250 if (!has_primary_as_parent)
251 LOG(ERROR) << "At least, one placement must have the primary as a parent.";
252 return has_primary_as_parent;
253 }
254
255 std::unique_ptr<DisplayLayout> DisplayLayout::Copy() const {
256 std::unique_ptr<DisplayLayout> copy(new DisplayLayout);
257 for (const auto& placement : placement_list)
258 copy->placement_list.push_back(placement);
259 copy->mirrored = mirrored;
260 copy->default_unified = default_unified;
261 copy->primary_id = primary_id;
262 return copy;
263 }
264
265 bool DisplayLayout::HasSamePlacementList(const DisplayLayout& layout) const {
266 if (placement_list.size() != layout.placement_list.size())
267 return false;
268 for (size_t index = 0; index < placement_list.size(); index++) {
269 const DisplayPlacement& placement1 = placement_list[index];
270 const DisplayPlacement& placement2 = layout.placement_list[index];
271 if (placement1.position != placement2.position ||
272 placement1.offset != placement2.offset ||
273 placement1.display_id != placement2.display_id ||
274 placement1.parent_display_id != placement2.parent_display_id) {
275 return false;
276 }
277 }
278 return true;
279 }
280
281 std::string DisplayLayout::ToString() const {
282 std::stringstream s;
283 s << "primary=" << primary_id;
284 if (mirrored)
285 s << ", mirrored";
286 if (default_unified)
287 s << ", default_unified";
288 bool added = false;
289 for (const auto& placement : placement_list) {
290 s << (added ? "),(" : " [(");
291 s << placement.ToString();
292 added = true;
293 }
294 if (added)
295 s << ")]";
296 return s.str();
297 }
298
299 DisplayPlacement DisplayLayout::FindPlacementById(int64_t display_id) const {
300 const auto iter =
301 std::find_if(placement_list.begin(), placement_list.end(),
302 [display_id](const DisplayPlacement& placement) {
303 return placement.display_id == display_id;
304 });
305 return (iter == placement_list.end()) ? DisplayPlacement()
306 : DisplayPlacement(*iter);
307 }
308
309 // static
310 bool DisplayLayout::ApplyDisplayPlacement(const DisplayPlacement& placement,
311 Displays* display_list,
312 int minimum_offset_overlap) {
313 const Display& parent_display =
314 *FindDisplayById(display_list, placement.parent_display_id);
315 DCHECK(parent_display.is_valid());
316 Display* target_display = FindDisplayById(display_list, placement.display_id);
317 gfx::Rect old_bounds(target_display->bounds());
318 DCHECK(target_display);
319
320 const gfx::Rect& parent_bounds = parent_display.bounds();
321 const gfx::Rect& target_bounds = target_display->bounds();
322 gfx::Point new_target_origin = parent_bounds.origin();
323
324 DisplayPlacement::Position position = placement.position;
325
326 // Ignore the offset in case the target display doesn't share edges with
327 // the parent display.
328 int offset = placement.offset;
329 if (position == DisplayPlacement::TOP ||
330 position == DisplayPlacement::BOTTOM) {
331 if (placement.offset_reference == DisplayPlacement::BOTTOM_RIGHT)
332 offset = parent_bounds.width() - offset - target_bounds.width();
333
334 offset = std::min(
335 offset, parent_bounds.width() - minimum_offset_overlap);
336 offset = std::max(
337 offset, -target_bounds.width() + minimum_offset_overlap);
338 } else {
339 if (placement.offset_reference == DisplayPlacement::BOTTOM_RIGHT)
340 offset = parent_bounds.height() - offset - target_bounds.height();
341
342 offset = std::min(
343 offset, parent_bounds.height() - minimum_offset_overlap);
344 offset = std::max(
345 offset, -target_bounds.height() + minimum_offset_overlap);
346 }
347 switch (position) {
348 case DisplayPlacement::TOP:
349 new_target_origin.Offset(offset, -target_bounds.height());
350 break;
351 case DisplayPlacement::RIGHT:
352 new_target_origin.Offset(parent_bounds.width(), offset);
353 break;
354 case DisplayPlacement::BOTTOM:
355 new_target_origin.Offset(offset, parent_bounds.height());
356 break;
357 case DisplayPlacement::LEFT:
358 new_target_origin.Offset(-target_bounds.width(), offset);
359 break;
360 }
361
362 gfx::Insets insets = target_display->GetWorkAreaInsets();
363 target_display->set_bounds(
364 gfx::Rect(new_target_origin, target_bounds.size()));
365 target_display->UpdateWorkAreaFromInsets(insets);
366
367 return old_bounds != target_display->bounds();
368 }
369
370 } // namespace display
OLDNEW
« no previous file with comments | « ui/display/manager/display_layout.h ('k') | ui/display/manager/display_layout_builder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698