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

Side by Side Diff: ui/display/fake_display_snapshot.cc

Issue 2395873002: Add more options to --screen-config flag. (Closed)
Patch Set: Improve tests and spec description. Created 4 years, 2 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
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/display/fake_display_snapshot.h" 5 #include "ui/display/fake_display_snapshot.h"
6 6
7 #include <inttypes.h> 7 #include <inttypes.h>
8 8
9 #include <sstream> 9 #include <sstream>
10 #include <utility> 10 #include <utility>
11 #include <vector> 11 #include <vector>
12 12
13 #include "base/memory/ptr_util.h" 13 #include "base/memory/ptr_util.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_split.h"
14 #include "base/strings/stringprintf.h" 16 #include "base/strings/stringprintf.h"
17 #include "third_party/re2/src/re2/re2.h"
18
19 using base::StringPiece;
15 20
16 namespace display { 21 namespace display {
17 22
18 namespace { 23 namespace {
19 24
20 static const float kInchInMm = 25.4f; 25 static const float kInchInMm = 25.4f;
21 26
22 // Get pixel pitch in millimeters from DPI. 27 // Get pixel pitch in millimeters from DPI.
23 float PixelPitchMmFromDPI(float dpi) { 28 float PixelPitchMmFromDPI(float dpi) {
24 return (1.0f / dpi) * kInchInMm; 29 return (1.0f / dpi) * kInchInMm;
(...skipping 30 matching lines...) Expand all
55 return "dp"; 60 return "dp";
56 case ui::DISPLAY_CONNECTION_TYPE_NETWORK: 61 case ui::DISPLAY_CONNECTION_TYPE_NETWORK:
57 return "network"; 62 return "network";
58 case ui::DISPLAY_CONNECTION_TYPE_VIRTUAL: 63 case ui::DISPLAY_CONNECTION_TYPE_VIRTUAL:
59 return "virtual"; 64 return "virtual";
60 } 65 }
61 NOTREACHED(); 66 NOTREACHED();
62 return ""; 67 return "";
63 } 68 }
64 69
70 // Extracts text after specified delimiter. If the delimiter doesn't exist then
Daniel Erat 2016/10/07 17:17:22 nit: "If the delimiter doesn't appear exactly once
kylechar 2016/10/11 13:56:49 Done.
71 // the result will be empty and the input string will be unmodified. Otherwise,
72 // the input string will contain the text before the delimiter and the result
73 // will be the text after the delimiter.
74 StringPiece ExtractSuffix(StringPiece* str, StringPiece delimiter) {
75 std::vector<StringPiece> parts = base::SplitStringPiece(
76 *str, delimiter, base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
77
78 if (parts.size() == 2) {
79 *str = parts[0];
80 return parts[1];
81 }
82
83 return StringPiece();
84 }
85
86 // Parses a display mode from |str| in the format HxW[%R], returning null if
87 // |str| is invalid.
88 std::unique_ptr<ui::DisplayMode> ParseDisplayMode(const std::string& str) {
89 int width = 0;
90 int height = 0;
91 float refresh_rate = 60.0f;
92
93 // With sscanf() it will happily ignore characters at the end of the string,
94 // so check |str| is valid using a regex.
95 if (!RE2::FullMatch(str, "\\d+x\\d+(?:%\\d+(?:\\.\\d*)?)?")) {
Daniel Erat 2016/10/07 17:17:22 since you're already using a regexp, why not extra
kylechar 2016/10/11 13:56:49 For the caveat I don't think it applies to the reg
96 LOG(ERROR) << "Invalid display mode string \"" << str << "\"";
97 return nullptr;
98 }
99
100 // Refresh rate is optional and will be be 60 if not specified.
101 if (sscanf(str.c_str(), "%dx%d%%%f", &width, &height, &refresh_rate) < 2) {
102 LOG(ERROR) << "Unable to parse display mode \"" << str << "\"";
103 return nullptr;
104 }
105
106 return base::MakeUnique<ui::DisplayMode>(gfx::Size(width, height), false,
107 refresh_rate);
108 }
109
110 // Parses a list of alternate display modes, adding each new display mode to
111 // |builder|. Returns false if any of the modes are invalid.
112 bool HandleModes(FakeDisplaySnapshot::Builder* builder,
113 StringPiece resolutions) {
114 for (const std::string& mode_str :
115 base::SplitString(resolutions, ":", base::TRIM_WHITESPACE,
116 base::SPLIT_WANT_NONEMPTY)) {
117 std::unique_ptr<ui::DisplayMode> mode = ParseDisplayMode(mode_str);
118 if (!mode)
119 return false;
120
121 builder->AddMode(std::move(mode));
122 }
123
124 return true;
125 }
126
127 // Parses device DPI and updates |builder|. Returns false if an invalid DPI
128 // string is provided.
129 bool HandleDPI(FakeDisplaySnapshot::Builder* builder, StringPiece dpi) {
130 if (dpi.empty())
131 return true;
132
133 int dpi_value = 0;
134 if (base::StringToInt(dpi, &dpi_value)) {
135 builder->SetDPI(dpi_value);
136 return true;
137 }
138
139 LOG(ERROR) << "Invalid DPI string \"" << dpi << "\"";
140 return false;
141 }
142
143 // Parses a list of display options and set each option true on |builder|.
144 // Returns false if any invalid options are provided. If an option appears more
145 // than once it will have no effect the second time.
146 bool HandleOptions(FakeDisplaySnapshot::Builder* builder, StringPiece options) {
147 for (size_t i = 0; i < options.size(); ++i) {
148 switch (options[i]) {
149 case 'o':
150 builder->SetHasOverscan(true);
151 break;
152 case 'c':
153 builder->SetHasColorCorrectionMatrix(true);
154 break;
155 case 'a':
156 builder->SetIsAspectPerservingScaling(true);
157 break;
158 case 'i':
159 builder->SetType(ui::DISPLAY_CONNECTION_TYPE_INTERNAL);
160 break;
161 default:
162 LOG(ERROR) << "Invalid option specifier \"" << options[i] << "\"";
163 return false;
164 }
165 }
166
167 return true;
168 }
169
65 } // namespace 170 } // namespace
66 171
67 using Builder = FakeDisplaySnapshot::Builder; 172 using Builder = FakeDisplaySnapshot::Builder;
68 173
69 Builder::Builder() {} 174 Builder::Builder() {}
70 175
71 Builder::~Builder() {} 176 Builder::~Builder() {}
72 177
73 std::unique_ptr<FakeDisplaySnapshot> Builder::Build() { 178 std::unique_ptr<FakeDisplaySnapshot> Builder::Build() {
74 if (modes_.empty() || id_ == Display::kInvalidDisplayID) { 179 if (modes_.empty() || id_ == Display::kInvalidDisplayID) {
75 NOTREACHED() << "Display modes or display ID missing"; 180 NOTREACHED() << "Display modes or display ID missing";
76 return nullptr; 181 return nullptr;
77 } 182 }
78 183
79 // If there is no native mode set, use the first display mode. 184 // If there is no native mode set, use the first display mode.
80 if (!native_mode_) 185 if (!native_mode_)
81 native_mode_ = modes_.back().get(); 186 native_mode_ = modes_.back().get();
82 187
83 // Calculate physical size to match set DPI. 188 // Calculate physical size to match set DPI.
84 gfx::Size physical_size = 189 gfx::Size physical_size =
85 gfx::ScaleToRoundedSize(native_mode_->size(), PixelPitchMmFromDPI(dpi_)); 190 gfx::ScaleToRoundedSize(native_mode_->size(), PixelPitchMmFromDPI(dpi_));
86 191
87 return base::WrapUnique(new FakeDisplaySnapshot( 192 return base::MakeUnique<FakeDisplaySnapshot>(
88 id_, origin_, physical_size, type_, is_aspect_preserving_scaling_, 193 id_, origin_, physical_size, type_, is_aspect_preserving_scaling_,
89 has_overscan_, has_color_correction_matrix_, name_, product_id_, 194 has_overscan_, has_color_correction_matrix_, name_, product_id_,
90 std::move(modes_), current_mode_, native_mode_)); 195 std::move(modes_), current_mode_, native_mode_);
91 } 196 }
92 197
93 Builder& Builder::SetId(int64_t id) { 198 Builder& Builder::SetId(int64_t id) {
94 id_ = id; 199 id_ = id;
95 return *this; 200 return *this;
96 } 201 }
97 202
98 Builder& Builder::SetNativeMode(const gfx::Size& size) { 203 Builder& Builder::SetNativeMode(const gfx::Size& size) {
99 native_mode_ = AddOrFindDisplayMode(size); 204 native_mode_ = AddOrFindDisplayMode(size);
100 return *this; 205 return *this;
101 } 206 }
102 207
208 Builder& Builder::SetNativeMode(std::unique_ptr<ui::DisplayMode> mode) {
209 native_mode_ = AddOrFindDisplayMode(std::move(mode));
210 return *this;
211 }
212
103 Builder& Builder::SetCurrentMode(const gfx::Size& size) { 213 Builder& Builder::SetCurrentMode(const gfx::Size& size) {
104 current_mode_ = AddOrFindDisplayMode(size); 214 current_mode_ = AddOrFindDisplayMode(size);
105 return *this; 215 return *this;
106 } 216 }
107 217
218 Builder& Builder::SetCurrentMode(std::unique_ptr<ui::DisplayMode> mode) {
219 current_mode_ = AddOrFindDisplayMode(std::move(mode));
220 return *this;
221 }
222
108 Builder& Builder::AddMode(const gfx::Size& size) { 223 Builder& Builder::AddMode(const gfx::Size& size) {
109 AddOrFindDisplayMode(size); 224 AddOrFindDisplayMode(size);
110 return *this; 225 return *this;
111 } 226 }
112 227
228 Builder& Builder::AddMode(std::unique_ptr<ui::DisplayMode> mode) {
229 AddOrFindDisplayMode(std::move(mode));
230 return *this;
231 }
232
113 Builder& Builder::SetOrigin(const gfx::Point& origin) { 233 Builder& Builder::SetOrigin(const gfx::Point& origin) {
114 origin_ = origin; 234 origin_ = origin;
115 return *this; 235 return *this;
116 } 236 }
117 237
118 Builder& Builder::SetType(ui::DisplayConnectionType type) { 238 Builder& Builder::SetType(ui::DisplayConnectionType type) {
119 type_ = type; 239 type_ = type;
120 return *this; 240 return *this;
121 } 241 }
122 242
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 for (auto& mode : modes_) { 282 for (auto& mode : modes_) {
163 if (mode->size() == size) 283 if (mode->size() == size)
164 return mode.get(); 284 return mode.get();
165 } 285 }
166 286
167 // Not found, insert a mode with the size and return. 287 // Not found, insert a mode with the size and return.
168 modes_.push_back(base::MakeUnique<ui::DisplayMode>(size, false, 60.0f)); 288 modes_.push_back(base::MakeUnique<ui::DisplayMode>(size, false, 60.0f));
169 return modes_.back().get(); 289 return modes_.back().get();
170 } 290 }
171 291
172 FakeDisplaySnapshot::FakeDisplaySnapshot( 292 const ui::DisplayMode* Builder::AddOrFindDisplayMode(
173 int64_t display_id, 293 std::unique_ptr<ui::DisplayMode> mode) {
174 const gfx::Point& origin, 294 for (auto& existing : modes_) {
175 const gfx::Size& physical_size, 295 if (mode->size() == existing->size() &&
176 ui::DisplayConnectionType type, 296 mode->is_interlaced() == existing->is_interlaced() &&
177 bool is_aspect_preserving_scaling, 297 mode->refresh_rate() == existing->refresh_rate())
178 bool has_overscan, 298 return existing.get();
179 bool has_color_correction_matrix, 299 }
180 std::string display_name, 300
181 int64_t product_id, 301 // Not found, insert mode and return.
182 std::vector<std::unique_ptr<const ui::DisplayMode>> modes, 302 modes_.push_back(std::move(mode));
183 const ui::DisplayMode* current_mode, 303 return modes_.back().get();
184 const ui::DisplayMode* native_mode) 304 }
305
306 FakeDisplaySnapshot::FakeDisplaySnapshot(int64_t display_id,
307 const gfx::Point& origin,
308 const gfx::Size& physical_size,
309 ui::DisplayConnectionType type,
310 bool is_aspect_preserving_scaling,
311 bool has_overscan,
312 bool has_color_correction_matrix,
313 std::string display_name,
314 int64_t product_id,
315 DisplayModeList modes,
316 const ui::DisplayMode* current_mode,
317 const ui::DisplayMode* native_mode)
185 : DisplaySnapshot(display_id, 318 : DisplaySnapshot(display_id,
186 origin, 319 origin,
187 physical_size, 320 physical_size,
188 type, 321 type,
189 is_aspect_preserving_scaling, 322 is_aspect_preserving_scaling,
190 has_overscan, 323 has_overscan,
191 has_color_correction_matrix, 324 has_color_correction_matrix,
192 display_name, 325 display_name,
193 base::FilePath(), 326 base::FilePath(),
194 std::move(modes), 327 std::move(modes),
195 std::vector<uint8_t>(), 328 std::vector<uint8_t>(),
196 current_mode, 329 current_mode,
197 native_mode) { 330 native_mode) {
198 product_id_ = product_id; 331 product_id_ = product_id;
199 } 332 }
200 333
201 FakeDisplaySnapshot::~FakeDisplaySnapshot() {} 334 FakeDisplaySnapshot::~FakeDisplaySnapshot() {}
202 335
336 // static
337 std::unique_ptr<ui::DisplaySnapshot> FakeDisplaySnapshot::CreateFromSpec(
338 int64_t id,
339 const std::string& spec) {
340 StringPiece leftover(spec);
341
342 // Cut off end of string at each delimiter to split.
343 StringPiece options = ExtractSuffix(&leftover, "/");
344 StringPiece dpi = ExtractSuffix(&leftover, "^");
345 StringPiece resolutions = ExtractSuffix(&leftover, "#");
346
347 // Leftovers should be just the native mode at this point.
348 std::unique_ptr<ui::DisplayMode> native_mode =
349 ParseDisplayMode(leftover.as_string());
350
351 // Fail without valid native mode.
352 if (!native_mode)
353 return nullptr;
354
355 FakeDisplaySnapshot::Builder builder;
356 builder.SetId(id).SetNativeMode(std::move(native_mode));
357 builder.SetName(base::StringPrintf("Fake Display %" PRId64, id));
358
359 if (!HandleModes(&builder, resolutions) || !HandleDPI(&builder, dpi) ||
360 !HandleOptions(&builder, options))
361 return nullptr;
362
363 return builder.Build();
364 }
365
203 std::string FakeDisplaySnapshot::ToString() const { 366 std::string FakeDisplaySnapshot::ToString() const {
204 return base::StringPrintf( 367 return base::StringPrintf(
205 "id=%" PRId64 368 "id=%" PRId64
206 " current_mode=%s native_mode=%s origin=%s" 369 " current_mode=%s native_mode=%s origin=%s"
207 " physical_size=%s, type=%s name=\"%s\" modes=(%s)", 370 " physical_size=%s, type=%s name=\"%s\" modes=(%s)",
208 display_id_, 371 display_id_,
209 current_mode_ ? current_mode_->ToString().c_str() : "nullptr", 372 current_mode_ ? current_mode_->ToString().c_str() : "nullptr",
210 native_mode_ ? native_mode_->ToString().c_str() : "nullptr", 373 native_mode_ ? native_mode_->ToString().c_str() : "nullptr",
211 origin_.ToString().c_str(), physical_size_.ToString().c_str(), 374 origin_.ToString().c_str(), physical_size_.ToString().c_str(),
212 DisplayConnectionTypeString(type_).c_str(), display_name_.c_str(), 375 DisplayConnectionTypeString(type_).c_str(), display_name_.c_str(),
213 ModeListString(modes_).c_str()); 376 ModeListString(modes_).c_str());
214 } 377 }
215 378
216 } // namespace display 379 } // namespace display
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698