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

Side by Side Diff: ash/display/display_info.cc

Issue 2084533008: mash: Migrate tray audio and deps to common. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Sync and rebase. Created 4 years, 6 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
« no previous file with comments | « ash/display/display_info.h ('k') | ash/display/display_info_unittest.cc » ('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 (c) 2013 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 "ash/display/display_info.h"
6
7 #include <stdio.h>
8
9 #include <algorithm>
10 #include <string>
11 #include <vector>
12
13 #include "base/logging.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_split.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/stringprintf.h"
18 #include "ui/display/display.h"
19 #include "ui/gfx/geometry/size_conversions.h"
20 #include "ui/gfx/geometry/size_f.h"
21
22 #if defined(OS_WIN)
23 #include "ui/aura/window_tree_host.h"
24 #include "ui/display/win/dpi.h"
25 #endif
26
27 namespace ash {
28 namespace {
29
30 // Use larger than max int to catch overflow early.
31 const int64_t kSynthesizedDisplayIdStart = 2200000000LL;
32
33 int64_t synthesized_display_id = kSynthesizedDisplayIdStart;
34
35 const float kDpi96 = 96.0;
36 bool use_125_dsf_for_ui_scaling = true;
37
38 // Check the content of |spec| and fill |bounds| and |device_scale_factor|.
39 // Returns true when |bounds| is found.
40 bool GetDisplayBounds(
41 const std::string& spec, gfx::Rect* bounds, float* device_scale_factor) {
42 int width = 0;
43 int height = 0;
44 int x = 0;
45 int y = 0;
46 if (sscanf(spec.c_str(), "%dx%d*%f",
47 &width, &height, device_scale_factor) >= 2 ||
48 sscanf(spec.c_str(), "%d+%d-%dx%d*%f", &x, &y, &width, &height,
49 device_scale_factor) >= 4) {
50 bounds->SetRect(x, y, width, height);
51 return true;
52 }
53 return false;
54 }
55
56 // Display mode list is sorted by:
57 // * the area in pixels in ascending order
58 // * refresh rate in descending order
59 struct DisplayModeSorter {
60 explicit DisplayModeSorter(bool is_internal) : is_internal(is_internal) {}
61
62 bool operator()(const DisplayMode& a, const DisplayMode& b) {
63 gfx::Size size_a_dip = a.GetSizeInDIP(is_internal);
64 gfx::Size size_b_dip = b.GetSizeInDIP(is_internal);
65 if (size_a_dip.GetArea() == size_b_dip.GetArea())
66 return (a.refresh_rate > b.refresh_rate);
67 return (size_a_dip.GetArea() < size_b_dip.GetArea());
68 }
69
70 bool is_internal;
71 };
72
73 } // namespace
74
75 DisplayMode::DisplayMode()
76 : refresh_rate(0.0f),
77 interlaced(false),
78 native(false),
79 ui_scale(1.0f),
80 device_scale_factor(1.0f) {}
81
82 DisplayMode::DisplayMode(const gfx::Size& size,
83 float refresh_rate,
84 bool interlaced,
85 bool native)
86 : size(size),
87 refresh_rate(refresh_rate),
88 interlaced(interlaced),
89 native(native),
90 ui_scale(1.0f),
91 device_scale_factor(1.0f) {}
92
93 gfx::Size DisplayMode::GetSizeInDIP(bool is_internal) const {
94 gfx::SizeF size_dip(size);
95 size_dip.Scale(ui_scale);
96 // DSF=1.25 is special on internal display. The screen is drawn with DSF=1.25
97 // but it doesn't affect the screen size computation.
98 if (use_125_dsf_for_ui_scaling && is_internal && device_scale_factor == 1.25f)
99 return gfx::ToFlooredSize(size_dip);
100 size_dip.Scale(1.0f / device_scale_factor);
101 return gfx::ToFlooredSize(size_dip);
102 }
103
104 bool DisplayMode::IsEquivalent(const DisplayMode& other) const {
105 const float kEpsilon = 0.0001f;
106 return size == other.size &&
107 std::abs(ui_scale - other.ui_scale) < kEpsilon &&
108 std::abs(device_scale_factor - other.device_scale_factor) < kEpsilon;
109 }
110
111 // satic
112 DisplayInfo DisplayInfo::CreateFromSpec(const std::string& spec) {
113 return CreateFromSpecWithID(spec, display::Display::kInvalidDisplayID);
114 }
115
116 // static
117 DisplayInfo DisplayInfo::CreateFromSpecWithID(const std::string& spec,
118 int64_t id) {
119 #if defined(OS_WIN)
120 gfx::Rect bounds_in_native(
121 gfx::Size(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)));
122 #else
123 // Default bounds for a display.
124 const int kDefaultHostWindowX = 200;
125 const int kDefaultHostWindowY = 200;
126 const int kDefaultHostWindowWidth = 1366;
127 const int kDefaultHostWindowHeight = 768;
128 gfx::Rect bounds_in_native(kDefaultHostWindowX, kDefaultHostWindowY,
129 kDefaultHostWindowWidth, kDefaultHostWindowHeight);
130 #endif
131 std::string main_spec = spec;
132
133 float ui_scale = 1.0f;
134 std::vector<std::string> parts = base::SplitString(
135 main_spec, "@", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
136 if (parts.size() == 2) {
137 double scale_in_double = 0;
138 if (base::StringToDouble(parts[1], &scale_in_double))
139 ui_scale = scale_in_double;
140 main_spec = parts[0];
141 }
142
143 parts = base::SplitString(main_spec, "/", base::KEEP_WHITESPACE,
144 base::SPLIT_WANT_NONEMPTY);
145 display::Display::Rotation rotation(display::Display::ROTATE_0);
146 bool has_overscan = false;
147 if (!parts.empty()) {
148 main_spec = parts[0];
149 if (parts.size() >= 2) {
150 std::string options = parts[1];
151 for (size_t i = 0; i < options.size(); ++i) {
152 char c = options[i];
153 switch (c) {
154 case 'o':
155 has_overscan = true;
156 break;
157 case 'r': // rotate 90 degrees to 'right'.
158 rotation = display::Display::ROTATE_90;
159 break;
160 case 'u': // 180 degrees, 'u'pside-down.
161 rotation = display::Display::ROTATE_180;
162 break;
163 case 'l': // rotate 90 degrees to 'left'.
164 rotation = display::Display::ROTATE_270;
165 break;
166 }
167 }
168 }
169 }
170
171 float device_scale_factor = 1.0f;
172 if (!GetDisplayBounds(main_spec, &bounds_in_native, &device_scale_factor)) {
173 #if defined(OS_WIN)
174 device_scale_factor = display::win::GetDPIScale();
175 #endif
176 }
177
178 std::vector<DisplayMode> display_modes;
179 parts = base::SplitString(main_spec, "#", base::KEEP_WHITESPACE,
180 base::SPLIT_WANT_NONEMPTY);
181 if (parts.size() == 2) {
182 size_t native_mode = 0;
183 int largest_area = -1;
184 float highest_refresh_rate = -1.0f;
185 main_spec = parts[0];
186 std::string resolution_list = parts[1];
187 parts = base::SplitString(resolution_list, "|", base::KEEP_WHITESPACE,
188 base::SPLIT_WANT_NONEMPTY);
189 for (size_t i = 0; i < parts.size(); ++i) {
190 DisplayMode mode;
191 gfx::Rect mode_bounds;
192 std::vector<std::string> resolution = base::SplitString(
193 parts[i], "%", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
194 if (GetDisplayBounds(
195 resolution[0], &mode_bounds, &mode.device_scale_factor)) {
196 mode.size = mode_bounds.size();
197 if (resolution.size() > 1)
198 sscanf(resolution[1].c_str(), "%f", &mode.refresh_rate);
199 if (mode.size.GetArea() >= largest_area &&
200 mode.refresh_rate > highest_refresh_rate) {
201 // Use mode with largest area and highest refresh rate as native.
202 largest_area = mode.size.GetArea();
203 highest_refresh_rate = mode.refresh_rate;
204 native_mode = i;
205 }
206 display_modes.push_back(mode);
207 }
208 }
209 display_modes[native_mode].native = true;
210 }
211
212 if (id == display::Display::kInvalidDisplayID)
213 id = synthesized_display_id++;
214 DisplayInfo display_info(
215 id, base::StringPrintf("Display-%d", static_cast<int>(id)), has_overscan);
216 display_info.set_device_scale_factor(device_scale_factor);
217 display_info.SetRotation(rotation, display::Display::ROTATION_SOURCE_ACTIVE);
218 display_info.set_configured_ui_scale(ui_scale);
219 display_info.SetBounds(bounds_in_native);
220 display_info.SetDisplayModes(display_modes);
221
222 // To test the overscan, it creates the default 5% overscan.
223 if (has_overscan) {
224 int width = bounds_in_native.width() / device_scale_factor / 40;
225 int height = bounds_in_native.height() / device_scale_factor / 40;
226 display_info.SetOverscanInsets(gfx::Insets(height, width, height, width));
227 display_info.UpdateDisplaySize();
228 }
229
230 DVLOG(1) << "DisplayInfoFromSpec info=" << display_info.ToString()
231 << ", spec=" << spec;
232 return display_info;
233 }
234
235 // static
236 void DisplayInfo::SetUse125DSFForUIScalingForTest(bool enable) {
237 use_125_dsf_for_ui_scaling = enable;
238 }
239
240 DisplayInfo::DisplayInfo()
241 : id_(display::Display::kInvalidDisplayID),
242 has_overscan_(false),
243 active_rotation_source_(display::Display::ROTATION_SOURCE_UNKNOWN),
244 touch_support_(display::Display::TOUCH_SUPPORT_UNKNOWN),
245 device_scale_factor_(1.0f),
246 device_dpi_(kDpi96),
247 overscan_insets_in_dip_(0, 0, 0, 0),
248 configured_ui_scale_(1.0f),
249 native_(false),
250 is_aspect_preserving_scaling_(false),
251 clear_overscan_insets_(false),
252 color_profile_(ui::COLOR_PROFILE_STANDARD) {}
253
254 DisplayInfo::DisplayInfo(int64_t id, const std::string& name, bool has_overscan)
255 : id_(id),
256 name_(name),
257 has_overscan_(has_overscan),
258 active_rotation_source_(display::Display::ROTATION_SOURCE_UNKNOWN),
259 touch_support_(display::Display::TOUCH_SUPPORT_UNKNOWN),
260 device_scale_factor_(1.0f),
261 device_dpi_(kDpi96),
262 overscan_insets_in_dip_(0, 0, 0, 0),
263 configured_ui_scale_(1.0f),
264 native_(false),
265 is_aspect_preserving_scaling_(false),
266 clear_overscan_insets_(false),
267 color_profile_(ui::COLOR_PROFILE_STANDARD) {}
268
269 DisplayInfo::DisplayInfo(const DisplayInfo& other) = default;
270
271 DisplayInfo::~DisplayInfo() {
272 }
273
274 void DisplayInfo::SetRotation(display::Display::Rotation rotation,
275 display::Display::RotationSource source) {
276 rotations_[source] = rotation;
277 rotations_[display::Display::ROTATION_SOURCE_ACTIVE] = rotation;
278 active_rotation_source_ = source;
279 }
280
281 display::Display::Rotation DisplayInfo::GetActiveRotation() const {
282 return GetRotation(display::Display::ROTATION_SOURCE_ACTIVE);
283 }
284
285 display::Display::Rotation DisplayInfo::GetRotation(
286 display::Display::RotationSource source) const {
287 if (rotations_.find(source) == rotations_.end())
288 return display::Display::ROTATE_0;
289 return rotations_.at(source);
290 }
291
292 void DisplayInfo::Copy(const DisplayInfo& native_info) {
293 DCHECK(id_ == native_info.id_);
294 name_ = native_info.name_;
295 has_overscan_ = native_info.has_overscan_;
296
297 active_rotation_source_ = native_info.active_rotation_source_;
298 touch_support_ = native_info.touch_support_;
299 input_devices_ = native_info.input_devices_;
300 device_scale_factor_ = native_info.device_scale_factor_;
301 DCHECK(!native_info.bounds_in_native_.IsEmpty());
302 bounds_in_native_ = native_info.bounds_in_native_;
303 device_dpi_ = native_info.device_dpi_;
304 size_in_pixel_ = native_info.size_in_pixel_;
305 is_aspect_preserving_scaling_ = native_info.is_aspect_preserving_scaling_;
306 display_modes_ = native_info.display_modes_;
307 available_color_profiles_ = native_info.available_color_profiles_;
308 maximum_cursor_size_ = native_info.maximum_cursor_size_;
309
310 // Rotation, ui_scale, color_profile and overscan are given by preference,
311 // or unit tests. Don't copy if this native_info came from
312 // DisplayChangeObserver.
313 if (!native_info.native()) {
314 // Update the overscan_insets_in_dip_ either if the inset should be
315 // cleared, or has non empty insts.
316 if (native_info.clear_overscan_insets())
317 overscan_insets_in_dip_.Set(0, 0, 0, 0);
318 else if (!native_info.overscan_insets_in_dip_.IsEmpty())
319 overscan_insets_in_dip_ = native_info.overscan_insets_in_dip_;
320
321 rotations_ = native_info.rotations_;
322 configured_ui_scale_ = native_info.configured_ui_scale_;
323 color_profile_ = native_info.color_profile();
324 }
325 }
326
327 void DisplayInfo::SetBounds(const gfx::Rect& new_bounds_in_native) {
328 bounds_in_native_ = new_bounds_in_native;
329 size_in_pixel_ = new_bounds_in_native.size();
330 UpdateDisplaySize();
331 }
332
333 float DisplayInfo::GetEffectiveDeviceScaleFactor() const {
334 if (Use125DSFForUIScaling() && device_scale_factor_ == 1.25f)
335 return (configured_ui_scale_ == 0.8f) ? 1.25f : 1.0f;
336 if (device_scale_factor_ == configured_ui_scale_)
337 return 1.0f;
338 return device_scale_factor_;
339 }
340
341 float DisplayInfo::GetEffectiveUIScale() const {
342 if (Use125DSFForUIScaling() && device_scale_factor_ == 1.25f)
343 return (configured_ui_scale_ == 0.8f) ? 1.0f : configured_ui_scale_;
344 if (device_scale_factor_ == configured_ui_scale_)
345 return 1.0f;
346 return configured_ui_scale_;
347 }
348
349 void DisplayInfo::UpdateDisplaySize() {
350 size_in_pixel_ = bounds_in_native_.size();
351 if (!overscan_insets_in_dip_.IsEmpty()) {
352 gfx::Insets insets_in_pixel =
353 overscan_insets_in_dip_.Scale(device_scale_factor_);
354 size_in_pixel_.Enlarge(-insets_in_pixel.width(), -insets_in_pixel.height());
355 } else {
356 overscan_insets_in_dip_.Set(0, 0, 0, 0);
357 }
358
359 if (GetActiveRotation() == display::Display::ROTATE_90 ||
360 GetActiveRotation() == display::Display::ROTATE_270) {
361 size_in_pixel_.SetSize(size_in_pixel_.height(), size_in_pixel_.width());
362 }
363 gfx::SizeF size_f(size_in_pixel_);
364 size_f.Scale(GetEffectiveUIScale());
365 size_in_pixel_ = gfx::ToFlooredSize(size_f);
366 }
367
368 void DisplayInfo::SetOverscanInsets(const gfx::Insets& insets_in_dip) {
369 overscan_insets_in_dip_ = insets_in_dip;
370 }
371
372 gfx::Insets DisplayInfo::GetOverscanInsetsInPixel() const {
373 return overscan_insets_in_dip_.Scale(device_scale_factor_);
374 }
375
376 void DisplayInfo::SetDisplayModes(
377 const std::vector<DisplayMode>& display_modes) {
378 display_modes_ = display_modes;
379 std::sort(display_modes_.begin(), display_modes_.end(),
380 DisplayModeSorter(display::Display::IsInternalDisplayId(id_)));
381 }
382
383 gfx::Size DisplayInfo::GetNativeModeSize() const {
384 for (size_t i = 0; i < display_modes_.size(); ++i) {
385 if (display_modes_[i].native)
386 return display_modes_[i].size;
387 }
388
389 return gfx::Size();
390 }
391
392 std::string DisplayInfo::ToString() const {
393 int rotation_degree = static_cast<int>(GetActiveRotation()) * 90;
394 std::string devices_str;
395
396 for (size_t i = 0; i < input_devices_.size(); ++i) {
397 devices_str += base::IntToString(input_devices_[i]);
398 if (i != input_devices_.size() - 1)
399 devices_str += ", ";
400 }
401
402 std::string result = base::StringPrintf(
403 "DisplayInfo[%lld] native bounds=%s, size=%s, scale=%f, "
404 "overscan=%s, rotation=%d, ui-scale=%f, touchscreen=%s, "
405 "input_devices=[%s]",
406 static_cast<long long int>(id_), bounds_in_native_.ToString().c_str(),
407 size_in_pixel_.ToString().c_str(), device_scale_factor_,
408 overscan_insets_in_dip_.ToString().c_str(), rotation_degree,
409 configured_ui_scale_,
410 touch_support_ == display::Display::TOUCH_SUPPORT_AVAILABLE
411 ? "yes"
412 : touch_support_ == display::Display::TOUCH_SUPPORT_UNAVAILABLE
413 ? "no"
414 : "unknown",
415 devices_str.c_str());
416
417 return result;
418 }
419
420 std::string DisplayInfo::ToFullString() const {
421 std::string display_modes_str;
422 std::vector<DisplayMode>::const_iterator iter = display_modes_.begin();
423 for (; iter != display_modes_.end(); ++iter) {
424 if (!display_modes_str.empty())
425 display_modes_str += ",";
426 base::StringAppendF(&display_modes_str,
427 "(%dx%d@%f%c%s)",
428 iter->size.width(),
429 iter->size.height(),
430 iter->refresh_rate,
431 iter->interlaced ? 'I' : 'P',
432 iter->native ? "(N)" : "");
433 }
434 return ToString() + ", display_modes==" + display_modes_str;
435 }
436
437 void DisplayInfo::SetColorProfile(ui::ColorCalibrationProfile profile) {
438 if (IsColorProfileAvailable(profile))
439 color_profile_ = profile;
440 }
441
442 bool DisplayInfo::IsColorProfileAvailable(
443 ui::ColorCalibrationProfile profile) const {
444 return std::find(available_color_profiles_.begin(),
445 available_color_profiles_.end(),
446 profile) != available_color_profiles_.end();
447 }
448
449 bool DisplayInfo::Use125DSFForUIScaling() const {
450 return use_125_dsf_for_ui_scaling &&
451 display::Display::IsInternalDisplayId(id_);
452 }
453
454 void DisplayInfo::AddInputDevice(int id) {
455 input_devices_.push_back(id);
456 }
457
458 void DisplayInfo::ClearInputDevices() {
459 input_devices_.clear();
460 }
461
462 void ResetDisplayIdForTest() {
463 synthesized_display_id = kSynthesizedDisplayIdStart;
464 }
465
466 } // namespace ash
OLDNEW
« no previous file with comments | « ash/display/display_info.h ('k') | ash/display/display_info_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698