| Index: ui/display/fake_display_snapshot.cc
|
| diff --git a/ui/display/fake_display_snapshot.cc b/ui/display/fake_display_snapshot.cc
|
| index a431a2a2f652418470ae1c24b3b7fbfb081d232a..f34177d5ad2f16537cb2613e68327aa6d4d6de9e 100644
|
| --- a/ui/display/fake_display_snapshot.cc
|
| +++ b/ui/display/fake_display_snapshot.cc
|
| @@ -11,7 +11,12 @@
|
| #include <vector>
|
|
|
| #include "base/memory/ptr_util.h"
|
| +#include "base/strings/string_number_conversions.h"
|
| +#include "base/strings/string_split.h"
|
| #include "base/strings/stringprintf.h"
|
| +#include "third_party/re2/src/re2/re2.h"
|
| +
|
| +using base::StringPiece;
|
|
|
| namespace display {
|
|
|
| @@ -62,6 +67,108 @@ std::string DisplayConnectionTypeString(ui::DisplayConnectionType type) {
|
| return "";
|
| }
|
|
|
| +// Extracts text after specified delimiter. If the delimiter doesn't appear
|
| +// exactly once the result will be empty and the input string will be
|
| +// unmodified. Otherwise, the input string will contain the text before the
|
| +// delimiter and the result will be the text after the delimiter.
|
| +StringPiece ExtractSuffix(StringPiece* str, StringPiece delimiter) {
|
| + std::vector<StringPiece> parts = base::SplitStringPiece(
|
| + *str, delimiter, base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
| +
|
| + if (parts.size() == 2) {
|
| + *str = parts[0];
|
| + return parts[1];
|
| + }
|
| +
|
| + return StringPiece();
|
| +}
|
| +
|
| +// Parses a display mode from |str| in the format HxW[%R], returning null if
|
| +// |str| is invalid.
|
| +std::unique_ptr<ui::DisplayMode> ParseDisplayMode(const std::string& str) {
|
| + int width = 0;
|
| + int height = 0;
|
| + std::string refresh_rate_str;
|
| +
|
| + // Check against regex and extract values.
|
| + if (!RE2::FullMatch(str, "(\\d+)x(\\d+)(?:%(\\d+\\.?\\d*))?", &width, &height,
|
| + &refresh_rate_str)) {
|
| + LOG(ERROR) << "Invalid display mode string \"" << str << "\"";
|
| + return nullptr;
|
| + }
|
| +
|
| + // Refresh rate is optional and will be be 60 if not specified.
|
| + double refresh_rate = 60.0f;
|
| + if (!refresh_rate_str.empty() &&
|
| + !base::StringToDouble(refresh_rate_str, &refresh_rate)) {
|
| + LOG(ERROR) << "Unable to parse display mode \"" << str << "\"";
|
| + return nullptr;
|
| + }
|
| +
|
| + return base::MakeUnique<ui::DisplayMode>(gfx::Size(width, height), false,
|
| + static_cast<float>(refresh_rate));
|
| +}
|
| +
|
| +// Parses a list of alternate display modes, adding each new display mode to
|
| +// |builder|. Returns false if any of the modes are invalid.
|
| +bool HandleModes(FakeDisplaySnapshot::Builder* builder,
|
| + StringPiece resolutions) {
|
| + for (const std::string& mode_str :
|
| + base::SplitString(resolutions, ":", base::TRIM_WHITESPACE,
|
| + base::SPLIT_WANT_NONEMPTY)) {
|
| + std::unique_ptr<ui::DisplayMode> mode = ParseDisplayMode(mode_str);
|
| + if (!mode)
|
| + return false;
|
| +
|
| + builder->AddMode(std::move(mode));
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +// Parses device DPI and updates |builder|. Returns false if an invalid DPI
|
| +// string is provided.
|
| +bool HandleDPI(FakeDisplaySnapshot::Builder* builder, StringPiece dpi) {
|
| + if (dpi.empty())
|
| + return true;
|
| +
|
| + int dpi_value = 0;
|
| + if (base::StringToInt(dpi, &dpi_value)) {
|
| + builder->SetDPI(dpi_value);
|
| + return true;
|
| + }
|
| +
|
| + LOG(ERROR) << "Invalid DPI string \"" << dpi << "\"";
|
| + return false;
|
| +}
|
| +
|
| +// Parses a list of display options and set each option true on |builder|.
|
| +// Returns false if any invalid options are provided. If an option appears more
|
| +// than once it will have no effect the second time.
|
| +bool HandleOptions(FakeDisplaySnapshot::Builder* builder, StringPiece options) {
|
| + for (size_t i = 0; i < options.size(); ++i) {
|
| + switch (options[i]) {
|
| + case 'o':
|
| + builder->SetHasOverscan(true);
|
| + break;
|
| + case 'c':
|
| + builder->SetHasColorCorrectionMatrix(true);
|
| + break;
|
| + case 'a':
|
| + builder->SetIsAspectPerservingScaling(true);
|
| + break;
|
| + case 'i':
|
| + builder->SetType(ui::DISPLAY_CONNECTION_TYPE_INTERNAL);
|
| + break;
|
| + default:
|
| + LOG(ERROR) << "Invalid option specifier \"" << options[i] << "\"";
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| } // namespace
|
|
|
| using Builder = FakeDisplaySnapshot::Builder;
|
| @@ -84,10 +191,10 @@ std::unique_ptr<FakeDisplaySnapshot> Builder::Build() {
|
| gfx::Size physical_size =
|
| gfx::ScaleToRoundedSize(native_mode_->size(), PixelPitchMmFromDPI(dpi_));
|
|
|
| - return base::WrapUnique(new FakeDisplaySnapshot(
|
| + return base::MakeUnique<FakeDisplaySnapshot>(
|
| id_, origin_, physical_size, type_, is_aspect_preserving_scaling_,
|
| has_overscan_, has_color_correction_matrix_, name_, product_id_,
|
| - std::move(modes_), current_mode_, native_mode_));
|
| + std::move(modes_), current_mode_, native_mode_);
|
| }
|
|
|
| Builder& Builder::SetId(int64_t id) {
|
| @@ -100,16 +207,31 @@ Builder& Builder::SetNativeMode(const gfx::Size& size) {
|
| return *this;
|
| }
|
|
|
| +Builder& Builder::SetNativeMode(std::unique_ptr<ui::DisplayMode> mode) {
|
| + native_mode_ = AddOrFindDisplayMode(std::move(mode));
|
| + return *this;
|
| +}
|
| +
|
| Builder& Builder::SetCurrentMode(const gfx::Size& size) {
|
| current_mode_ = AddOrFindDisplayMode(size);
|
| return *this;
|
| }
|
|
|
| +Builder& Builder::SetCurrentMode(std::unique_ptr<ui::DisplayMode> mode) {
|
| + current_mode_ = AddOrFindDisplayMode(std::move(mode));
|
| + return *this;
|
| +}
|
| +
|
| Builder& Builder::AddMode(const gfx::Size& size) {
|
| AddOrFindDisplayMode(size);
|
| return *this;
|
| }
|
|
|
| +Builder& Builder::AddMode(std::unique_ptr<ui::DisplayMode> mode) {
|
| + AddOrFindDisplayMode(std::move(mode));
|
| + return *this;
|
| +}
|
| +
|
| Builder& Builder::SetOrigin(const gfx::Point& origin) {
|
| origin_ = origin;
|
| return *this;
|
| @@ -169,19 +291,32 @@ const ui::DisplayMode* Builder::AddOrFindDisplayMode(const gfx::Size& size) {
|
| return modes_.back().get();
|
| }
|
|
|
| -FakeDisplaySnapshot::FakeDisplaySnapshot(
|
| - int64_t display_id,
|
| - const gfx::Point& origin,
|
| - const gfx::Size& physical_size,
|
| - ui::DisplayConnectionType type,
|
| - bool is_aspect_preserving_scaling,
|
| - bool has_overscan,
|
| - bool has_color_correction_matrix,
|
| - std::string display_name,
|
| - int64_t product_id,
|
| - std::vector<std::unique_ptr<const ui::DisplayMode>> modes,
|
| - const ui::DisplayMode* current_mode,
|
| - const ui::DisplayMode* native_mode)
|
| +const ui::DisplayMode* Builder::AddOrFindDisplayMode(
|
| + std::unique_ptr<ui::DisplayMode> mode) {
|
| + for (auto& existing : modes_) {
|
| + if (mode->size() == existing->size() &&
|
| + mode->is_interlaced() == existing->is_interlaced() &&
|
| + mode->refresh_rate() == existing->refresh_rate())
|
| + return existing.get();
|
| + }
|
| +
|
| + // Not found, insert mode and return.
|
| + modes_.push_back(std::move(mode));
|
| + return modes_.back().get();
|
| +}
|
| +
|
| +FakeDisplaySnapshot::FakeDisplaySnapshot(int64_t display_id,
|
| + const gfx::Point& origin,
|
| + const gfx::Size& physical_size,
|
| + ui::DisplayConnectionType type,
|
| + bool is_aspect_preserving_scaling,
|
| + bool has_overscan,
|
| + bool has_color_correction_matrix,
|
| + std::string display_name,
|
| + int64_t product_id,
|
| + DisplayModeList modes,
|
| + const ui::DisplayMode* current_mode,
|
| + const ui::DisplayMode* native_mode)
|
| : DisplaySnapshot(display_id,
|
| origin,
|
| physical_size,
|
| @@ -200,6 +335,36 @@ FakeDisplaySnapshot::FakeDisplaySnapshot(
|
|
|
| FakeDisplaySnapshot::~FakeDisplaySnapshot() {}
|
|
|
| +// static
|
| +std::unique_ptr<ui::DisplaySnapshot> FakeDisplaySnapshot::CreateFromSpec(
|
| + int64_t id,
|
| + const std::string& spec) {
|
| + StringPiece leftover(spec);
|
| +
|
| + // Cut off end of string at each delimiter to split.
|
| + StringPiece options = ExtractSuffix(&leftover, "/");
|
| + StringPiece dpi = ExtractSuffix(&leftover, "^");
|
| + StringPiece resolutions = ExtractSuffix(&leftover, "#");
|
| +
|
| + // Leftovers should be just the native mode at this point.
|
| + std::unique_ptr<ui::DisplayMode> native_mode =
|
| + ParseDisplayMode(leftover.as_string());
|
| +
|
| + // Fail without valid native mode.
|
| + if (!native_mode)
|
| + return nullptr;
|
| +
|
| + FakeDisplaySnapshot::Builder builder;
|
| + builder.SetId(id).SetNativeMode(std::move(native_mode));
|
| + builder.SetName(base::StringPrintf("Fake Display %" PRId64, id));
|
| +
|
| + if (!HandleModes(&builder, resolutions) || !HandleDPI(&builder, dpi) ||
|
| + !HandleOptions(&builder, options))
|
| + return nullptr;
|
| +
|
| + return builder.Build();
|
| +}
|
| +
|
| std::string FakeDisplaySnapshot::ToString() const {
|
| return base::StringPrintf(
|
| "id=%" PRId64
|
|
|