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

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

Issue 2270553002: Move ash::DisplayInfo to ui (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: build Created 4 years, 3 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "ash/display/display_manager.h" 5 #include "ash/display/display_manager.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 #include <limits> 9 #include <limits>
10 #include <map> 10 #include <map>
11 #include <set> 11 #include <set>
12 #include <string> 12 #include <string>
13 #include <utility> 13 #include <utility>
14 #include <vector> 14 #include <vector>
15 15
16 #include "ash/common/ash_switches.h" 16 #include "ash/common/ash_switches.h"
17 #include "ash/common/display/display_info.h"
18 #include "ash/display/display_util.h" 17 #include "ash/display/display_util.h"
19 #include "ash/display/extended_mouse_warp_controller.h" 18 #include "ash/display/extended_mouse_warp_controller.h"
20 #include "ash/display/null_mouse_warp_controller.h" 19 #include "ash/display/null_mouse_warp_controller.h"
21 #include "ash/display/screen_ash.h" 20 #include "ash/display/screen_ash.h"
22 #include "ash/display/unified_mouse_warp_controller.h" 21 #include "ash/display/unified_mouse_warp_controller.h"
23 #include "ash/screen_util.h" 22 #include "ash/screen_util.h"
24 #include "ash/shell.h" 23 #include "ash/shell.h"
25 #include "base/auto_reset.h" 24 #include "base/auto_reset.h"
26 #include "base/command_line.h" 25 #include "base/command_line.h"
27 #include "base/logging.h" 26 #include "base/logging.h"
28 #include "base/memory/ptr_util.h" 27 #include "base/memory/ptr_util.h"
29 #include "base/metrics/histogram.h" 28 #include "base/metrics/histogram.h"
30 #include "base/run_loop.h" 29 #include "base/run_loop.h"
31 #include "base/strings/string_number_conversions.h" 30 #include "base/strings/string_number_conversions.h"
32 #include "base/strings/string_split.h" 31 #include "base/strings/string_split.h"
33 #include "base/strings/stringprintf.h" 32 #include "base/strings/stringprintf.h"
34 #include "base/strings/utf_string_conversions.h" 33 #include "base/strings/utf_string_conversions.h"
35 #include "base/threading/thread_task_runner_handle.h" 34 #include "base/threading/thread_task_runner_handle.h"
36 #include "grit/ash_strings.h" 35 #include "grit/ash_strings.h"
37 #include "ui/base/l10n/l10n_util.h" 36 #include "ui/base/l10n/l10n_util.h"
38 #include "ui/display/display.h" 37 #include "ui/display/display.h"
39 #include "ui/display/display_observer.h" 38 #include "ui/display/display_observer.h"
40 #include "ui/display/manager/display_layout_store.h" 39 #include "ui/display/manager/display_layout_store.h"
40 #include "ui/display/manager/managed_display_info.h"
41 #include "ui/display/screen.h" 41 #include "ui/display/screen.h"
42 #include "ui/gfx/font_render_params.h" 42 #include "ui/gfx/font_render_params.h"
43 #include "ui/gfx/geometry/rect.h" 43 #include "ui/gfx/geometry/rect.h"
44 #include "ui/gfx/geometry/size_conversions.h" 44 #include "ui/gfx/geometry/size_conversions.h"
45 45
46 #if defined(USE_X11) 46 #if defined(USE_X11)
47 #include "ui/base/x/x11_util.h" // nogncheck 47 #include "ui/base/x/x11_util.h" // nogncheck
48 #endif 48 #endif
49 49
50 #if defined(OS_CHROMEOS) 50 #if defined(OS_CHROMEOS)
51 #include "base/sys_info.h" 51 #include "base/sys_info.h"
52 #endif 52 #endif
53 53
54 #if defined(OS_WIN) 54 #if defined(OS_WIN)
55 #include "base/win/windows_version.h" 55 #include "base/win/windows_version.h"
56 #endif 56 #endif
57 57
58 namespace ash { 58 namespace ash {
59 typedef std::vector<DisplayInfo> DisplayInfoList;
60 59
61 namespace { 60 namespace {
62 61
63 // We need to keep this in order for unittests to tell if 62 // We need to keep this in order for unittests to tell if
64 // the object in display::Screen::GetScreenByType is for shutdown. 63 // the object in display::Screen::GetScreenByType is for shutdown.
65 display::Screen* screen_for_shutdown = nullptr; 64 display::Screen* screen_for_shutdown = nullptr;
66 65
67 // The number of pixels to overlap between the primary and secondary displays, 66 // The number of pixels to overlap between the primary and secondary displays,
68 // in case that the offset value is too large. 67 // in case that the offset value is too large.
69 const int kMinimumOverlapForInvalidOffset = 100; 68 const int kMinimumOverlapForInvalidOffset = 100;
70 69
71 struct DisplaySortFunctor { 70 struct DisplaySortFunctor {
72 bool operator()(const display::Display& a, const display::Display& b) { 71 bool operator()(const display::Display& a, const display::Display& b) {
73 return CompareDisplayIds(a.id(), b.id()); 72 return CompareDisplayIds(a.id(), b.id());
74 } 73 }
75 }; 74 };
76 75
77 struct DisplayInfoSortFunctor { 76 struct DisplayInfoSortFunctor {
78 bool operator()(const DisplayInfo& a, const DisplayInfo& b) { 77 bool operator()(const ui::ManagedDisplayInfo& a,
78 const ui::ManagedDisplayInfo& b) {
79 return CompareDisplayIds(a.id(), b.id()); 79 return CompareDisplayIds(a.id(), b.id());
80 } 80 }
81 }; 81 };
82 82
83 display::Display& GetInvalidDisplay() { 83 display::Display& GetInvalidDisplay() {
84 static display::Display* invalid_display = new display::Display(); 84 static display::Display* invalid_display = new display::Display();
85 return *invalid_display; 85 return *invalid_display;
86 } 86 }
87 87
88 DisplayInfo::ManagedDisplayModeList::const_iterator FindDisplayMode( 88 ui::ManagedDisplayInfo::ManagedDisplayModeList::const_iterator FindDisplayMode(
89 const DisplayInfo& info, 89 const ui::ManagedDisplayInfo& info,
90 const scoped_refptr<ManagedDisplayMode>& target_mode) { 90 const scoped_refptr<ui::ManagedDisplayMode>& target_mode) {
91 const DisplayInfo::ManagedDisplayModeList& modes = info.display_modes(); 91 const ui::ManagedDisplayInfo::ManagedDisplayModeList& modes =
92 info.display_modes();
92 return std::find_if( 93 return std::find_if(
93 modes.begin(), modes.end(), 94 modes.begin(), modes.end(),
94 [target_mode](const scoped_refptr<ManagedDisplayMode>& mode) { 95 [target_mode](const scoped_refptr<ui::ManagedDisplayMode>& mode) {
95 return target_mode->IsEquivalent(mode); 96 return target_mode->IsEquivalent(mode);
96 }); 97 });
97 } 98 }
98 99
99 void SetInternalManagedDisplayModeList(DisplayInfo* info) { 100 void SetInternalManagedDisplayModeList(ui::ManagedDisplayInfo* info) {
100 scoped_refptr<ManagedDisplayMode> native_mode = new ManagedDisplayMode( 101 scoped_refptr<ui::ManagedDisplayMode> native_mode =
101 info->bounds_in_native().size(), 0.0 /* refresh_rate */, 102 new ui::ManagedDisplayMode(info->bounds_in_native().size(),
102 false /* interlaced */, false /* native_mode */, 1.0 /* ui_scale */, 103 0.0 /* refresh_rate */, false /* interlaced */,
103 info->device_scale_factor()); 104 false /* native_mode */, 1.0 /* ui_scale */,
105 info->device_scale_factor());
104 info->SetManagedDisplayModes( 106 info->SetManagedDisplayModes(
105 CreateInternalManagedDisplayModeList(native_mode)); 107 CreateInternalManagedDisplayModeList(native_mode));
106 } 108 }
107 109
108 void MaybeInitInternalDisplay(DisplayInfo* info) { 110 void MaybeInitInternalDisplay(ui::ManagedDisplayInfo* info) {
109 int64_t id = info->id(); 111 int64_t id = info->id();
110 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); 112 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
111 if (command_line->HasSwitch(switches::kAshUseFirstDisplayAsInternal)) { 113 if (command_line->HasSwitch(switches::kAshUseFirstDisplayAsInternal)) {
112 display::Display::SetInternalDisplayId(id); 114 display::Display::SetInternalDisplayId(id);
113 SetInternalManagedDisplayModeList(info); 115 SetInternalManagedDisplayModeList(info);
114 } 116 }
115 } 117 }
116 118
117 gfx::Size GetMaxNativeSize(const DisplayInfo& info) { 119 gfx::Size GetMaxNativeSize(const ui::ManagedDisplayInfo& info) {
118 gfx::Size size; 120 gfx::Size size;
119 for (auto& mode : info.display_modes()) { 121 for (auto& mode : info.display_modes()) {
120 if (mode->size().GetArea() > size.GetArea()) 122 if (mode->size().GetArea() > size.GetArea())
121 size = mode->size(); 123 size = mode->size();
122 } 124 }
123 return size; 125 return size;
124 } 126 }
125 127
126 } // namespace 128 } // namespace
127 129
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 169
168 bool DisplayManager::InitFromCommandLine() { 170 bool DisplayManager::InitFromCommandLine() {
169 DisplayInfoList info_list; 171 DisplayInfoList info_list;
170 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); 172 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
171 if (!command_line->HasSwitch(switches::kAshHostWindowBounds)) 173 if (!command_line->HasSwitch(switches::kAshHostWindowBounds))
172 return false; 174 return false;
173 const string size_str = 175 const string size_str =
174 command_line->GetSwitchValueASCII(switches::kAshHostWindowBounds); 176 command_line->GetSwitchValueASCII(switches::kAshHostWindowBounds);
175 for (const std::string& part : base::SplitString( 177 for (const std::string& part : base::SplitString(
176 size_str, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) { 178 size_str, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
177 info_list.push_back(DisplayInfo::CreateFromSpec(part)); 179 info_list.push_back(ui::ManagedDisplayInfo::CreateFromSpec(part));
178 info_list.back().set_native(true); 180 info_list.back().set_native(true);
179 } 181 }
180 MaybeInitInternalDisplay(&info_list[0]); 182 MaybeInitInternalDisplay(&info_list[0]);
181 if (info_list.size() > 1 && 183 if (info_list.size() > 1 &&
182 command_line->HasSwitch(switches::kAshEnableSoftwareMirroring)) { 184 command_line->HasSwitch(switches::kAshEnableSoftwareMirroring)) {
183 SetMultiDisplayMode(MIRRORING); 185 SetMultiDisplayMode(MIRRORING);
184 } 186 }
185 OnNativeDisplaysChanged(info_list); 187 OnNativeDisplaysChanged(info_list);
186 return true; 188 return true;
187 } 189 }
188 190
189 void DisplayManager::InitDefaultDisplay() { 191 void DisplayManager::InitDefaultDisplay() {
190 DisplayInfoList info_list; 192 DisplayInfoList info_list;
191 info_list.push_back(DisplayInfo::CreateFromSpec(std::string())); 193 info_list.push_back(ui::ManagedDisplayInfo::CreateFromSpec(std::string()));
192 info_list.back().set_native(true); 194 info_list.back().set_native(true);
193 MaybeInitInternalDisplay(&info_list[0]); 195 MaybeInitInternalDisplay(&info_list[0]);
194 OnNativeDisplaysChanged(info_list); 196 OnNativeDisplaysChanged(info_list);
195 } 197 }
196 198
197 void DisplayManager::RefreshFontParams() { 199 void DisplayManager::RefreshFontParams() {
198 #if defined(OS_CHROMEOS) 200 #if defined(OS_CHROMEOS)
199 // Use the largest device scale factor among currently active displays. Non 201 // Use the largest device scale factor among currently active displays. Non
200 // internal display may have bigger scale factor in case the external display 202 // internal display may have bigger scale factor in case the external display
201 // is an 4K display. 203 // is an 4K display.
202 float largest_device_scale_factor = 1.0f; 204 float largest_device_scale_factor = 1.0f;
203 for (const display::Display& display : active_display_list_) { 205 for (const display::Display& display : active_display_list_) {
204 const ash::DisplayInfo& info = display_info_[display.id()]; 206 const ui::ManagedDisplayInfo& info = display_info_[display.id()];
205 largest_device_scale_factor = std::max( 207 largest_device_scale_factor = std::max(
206 largest_device_scale_factor, info.GetEffectiveDeviceScaleFactor()); 208 largest_device_scale_factor, info.GetEffectiveDeviceScaleFactor());
207 } 209 }
208 gfx::SetFontRenderParamsDeviceScaleFactor(largest_device_scale_factor); 210 gfx::SetFontRenderParamsDeviceScaleFactor(largest_device_scale_factor);
209 #endif // OS_CHROMEOS 211 #endif // OS_CHROMEOS
210 } 212 }
211 213
212 const display::DisplayLayout& DisplayManager::GetCurrentDisplayLayout() const { 214 const display::DisplayLayout& DisplayManager::GetCurrentDisplayLayout() const {
213 DCHECK_LE(2U, num_connected_displays()); 215 DCHECK_LE(2U, num_connected_displays());
214 if (num_connected_displays() > 1) { 216 if (num_connected_displays() > 1) {
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 *display, display::DisplayObserver::DISPLAY_METRIC_WORK_AREA); 300 *display, display::DisplayObserver::DISPLAY_METRIC_WORK_AREA);
299 } 301 }
300 return workarea_changed; 302 return workarea_changed;
301 } 303 }
302 304
303 void DisplayManager::SetOverscanInsets(int64_t display_id, 305 void DisplayManager::SetOverscanInsets(int64_t display_id,
304 const gfx::Insets& insets_in_dip) { 306 const gfx::Insets& insets_in_dip) {
305 bool update = false; 307 bool update = false;
306 DisplayInfoList display_info_list; 308 DisplayInfoList display_info_list;
307 for (const auto& display : active_display_list_) { 309 for (const auto& display : active_display_list_) {
308 DisplayInfo info = GetDisplayInfo(display.id()); 310 ui::ManagedDisplayInfo info = GetDisplayInfo(display.id());
309 if (info.id() == display_id) { 311 if (info.id() == display_id) {
310 if (insets_in_dip.IsEmpty()) { 312 if (insets_in_dip.IsEmpty()) {
311 info.set_clear_overscan_insets(true); 313 info.set_clear_overscan_insets(true);
312 } else { 314 } else {
313 info.set_clear_overscan_insets(false); 315 info.set_clear_overscan_insets(false);
314 info.SetOverscanInsets(insets_in_dip); 316 info.SetOverscanInsets(insets_in_dip);
315 } 317 }
316 update = true; 318 update = true;
317 } 319 }
318 display_info_list.push_back(info); 320 display_info_list.push_back(info);
319 } 321 }
320 if (update) { 322 if (update) {
321 AddMirrorDisplayInfoIfAny(&display_info_list); 323 AddMirrorDisplayInfoIfAny(&display_info_list);
322 UpdateDisplaysWith(display_info_list); 324 UpdateDisplaysWith(display_info_list);
323 } else { 325 } else {
324 display_info_[display_id].SetOverscanInsets(insets_in_dip); 326 display_info_[display_id].SetOverscanInsets(insets_in_dip);
325 } 327 }
326 } 328 }
327 329
328 void DisplayManager::SetDisplayRotation( 330 void DisplayManager::SetDisplayRotation(
329 int64_t display_id, 331 int64_t display_id,
330 display::Display::Rotation rotation, 332 display::Display::Rotation rotation,
331 display::Display::RotationSource source) { 333 display::Display::RotationSource source) {
332 if (IsInUnifiedMode()) 334 if (IsInUnifiedMode())
333 return; 335 return;
334 336
335 DisplayInfoList display_info_list; 337 DisplayInfoList display_info_list;
336 bool is_active = false; 338 bool is_active = false;
337 for (const auto& display : active_display_list_) { 339 for (const auto& display : active_display_list_) {
338 DisplayInfo info = GetDisplayInfo(display.id()); 340 ui::ManagedDisplayInfo info = GetDisplayInfo(display.id());
339 if (info.id() == display_id) { 341 if (info.id() == display_id) {
340 if (info.GetRotation(source) == rotation && 342 if (info.GetRotation(source) == rotation &&
341 info.GetActiveRotation() == rotation) { 343 info.GetActiveRotation() == rotation) {
342 return; 344 return;
343 } 345 }
344 info.SetRotation(rotation, source); 346 info.SetRotation(rotation, source);
345 is_active = true; 347 is_active = true;
346 } 348 }
347 display_info_list.push_back(info); 349 display_info_list.push_back(info);
348 } 350 }
349 if (is_active) { 351 if (is_active) {
350 AddMirrorDisplayInfoIfAny(&display_info_list); 352 AddMirrorDisplayInfoIfAny(&display_info_list);
351 UpdateDisplaysWith(display_info_list); 353 UpdateDisplaysWith(display_info_list);
352 } else if (display_info_.find(display_id) != display_info_.end()) { 354 } else if (display_info_.find(display_id) != display_info_.end()) {
353 // Inactive displays can reactivate, ensure they have been updated. 355 // Inactive displays can reactivate, ensure they have been updated.
354 display_info_[display_id].SetRotation(rotation, source); 356 display_info_[display_id].SetRotation(rotation, source);
355 } 357 }
356 } 358 }
357 359
358 bool DisplayManager::SetDisplayMode( 360 bool DisplayManager::SetDisplayMode(
359 int64_t display_id, 361 int64_t display_id,
360 const scoped_refptr<ManagedDisplayMode>& display_mode) { 362 const scoped_refptr<ui::ManagedDisplayMode>& display_mode) {
361 bool change_ui_scale = GetDisplayIdForUIScaling() == display_id; 363 bool change_ui_scale = GetDisplayIdForUIScaling() == display_id;
362 364
363 DisplayInfoList display_info_list; 365 DisplayInfoList display_info_list;
364 bool display_property_changed = false; 366 bool display_property_changed = false;
365 bool resolution_changed = false; 367 bool resolution_changed = false;
366 for (const auto& display : active_display_list_) { 368 for (const auto& display : active_display_list_) {
367 DisplayInfo info = GetDisplayInfo(display.id()); 369 ui::ManagedDisplayInfo info = GetDisplayInfo(display.id());
368 if (info.id() == display_id) { 370 if (info.id() == display_id) {
369 auto iter = FindDisplayMode(info, display_mode); 371 auto iter = FindDisplayMode(info, display_mode);
370 if (iter == info.display_modes().end()) { 372 if (iter == info.display_modes().end()) {
371 LOG(WARNING) << "Unsupported display mode was requested:" 373 LOG(WARNING) << "Unsupported display mode was requested:"
372 << "size=" << display_mode->size().ToString() 374 << "size=" << display_mode->size().ToString()
373 << ", ui scale=" << display_mode->ui_scale() 375 << ", ui scale=" << display_mode->ui_scale()
374 << ", scale factor=" 376 << ", scale factor="
375 << display_mode->device_scale_factor(); 377 << display_mode->device_scale_factor();
376 return false; 378 return false;
377 } 379 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 411
410 void DisplayManager::RegisterDisplayProperty( 412 void DisplayManager::RegisterDisplayProperty(
411 int64_t display_id, 413 int64_t display_id,
412 display::Display::Rotation rotation, 414 display::Display::Rotation rotation,
413 float ui_scale, 415 float ui_scale,
414 const gfx::Insets* overscan_insets, 416 const gfx::Insets* overscan_insets,
415 const gfx::Size& resolution_in_pixels, 417 const gfx::Size& resolution_in_pixels,
416 float device_scale_factor, 418 float device_scale_factor,
417 ui::ColorCalibrationProfile color_profile) { 419 ui::ColorCalibrationProfile color_profile) {
418 if (display_info_.find(display_id) == display_info_.end()) 420 if (display_info_.find(display_id) == display_info_.end())
419 display_info_[display_id] = DisplayInfo(display_id, std::string(), false); 421 display_info_[display_id] =
422 ui::ManagedDisplayInfo(display_id, std::string(), false);
420 423
421 // Do not allow rotation in unified desktop mode. 424 // Do not allow rotation in unified desktop mode.
422 if (display_id == kUnifiedDisplayId) 425 if (display_id == kUnifiedDisplayId)
423 rotation = display::Display::ROTATE_0; 426 rotation = display::Display::ROTATE_0;
424 427
425 display_info_[display_id].SetRotation(rotation, 428 display_info_[display_id].SetRotation(rotation,
426 display::Display::ROTATION_SOURCE_USER); 429 display::Display::ROTATION_SOURCE_USER);
427 display_info_[display_id].SetRotation( 430 display_info_[display_id].SetRotation(
428 rotation, display::Display::ROTATION_SOURCE_ACTIVE); 431 rotation, display::Display::ROTATION_SOURCE_ACTIVE);
429 display_info_[display_id].SetColorProfile(color_profile); 432 display_info_[display_id].SetColorProfile(color_profile);
430 // Just in case the preference file was corrupted. 433 // Just in case the preference file was corrupted.
431 // TODO(mukai): register |display_modes_| here as well, so the lookup for the 434 // TODO(mukai): register |display_modes_| here as well, so the lookup for the
432 // default mode in GetActiveModeForDisplayId() gets much simpler. 435 // default mode in GetActiveModeForDisplayId() gets much simpler.
433 if (0.5f <= ui_scale && ui_scale <= 2.0f) 436 if (0.5f <= ui_scale && ui_scale <= 2.0f)
434 display_info_[display_id].set_configured_ui_scale(ui_scale); 437 display_info_[display_id].set_configured_ui_scale(ui_scale);
435 if (overscan_insets) 438 if (overscan_insets)
436 display_info_[display_id].SetOverscanInsets(*overscan_insets); 439 display_info_[display_id].SetOverscanInsets(*overscan_insets);
437 if (!resolution_in_pixels.IsEmpty()) { 440 if (!resolution_in_pixels.IsEmpty()) {
438 DCHECK(!display::Display::IsInternalDisplayId(display_id)); 441 DCHECK(!display::Display::IsInternalDisplayId(display_id));
439 // Default refresh rate, until OnNativeDisplaysChanged() updates us with the 442 // Default refresh rate, until OnNativeDisplaysChanged() updates us with the
440 // actual display info, is 60 Hz. 443 // actual display info, is 60 Hz.
441 scoped_refptr<ManagedDisplayMode> mode = new ManagedDisplayMode( 444 scoped_refptr<ui::ManagedDisplayMode> mode = new ui::ManagedDisplayMode(
442 resolution_in_pixels, 60.0f, false, false, 1.0, device_scale_factor); 445 resolution_in_pixels, 60.0f, false, false, 1.0, device_scale_factor);
443 display_modes_[display_id] = mode; 446 display_modes_[display_id] = mode;
444 } 447 }
445 } 448 }
446 449
447 scoped_refptr<ManagedDisplayMode> DisplayManager::GetActiveModeForDisplayId( 450 scoped_refptr<ui::ManagedDisplayMode> DisplayManager::GetActiveModeForDisplayId(
448 int64_t display_id) const { 451 int64_t display_id) const {
449 scoped_refptr<ManagedDisplayMode> selected_mode( 452 scoped_refptr<ui::ManagedDisplayMode> selected_mode(
450 GetSelectedModeForDisplayId(display_id)); 453 GetSelectedModeForDisplayId(display_id));
451 if (selected_mode) 454 if (selected_mode)
452 return selected_mode; 455 return selected_mode;
453 456
454 // If 'selected' mode is empty, it should return the default mode. This means 457 // If 'selected' mode is empty, it should return the default mode. This means
455 // the native mode for the external display. Unfortunately this is not true 458 // the native mode for the external display. Unfortunately this is not true
456 // for the internal display because restoring UI-scale doesn't register the 459 // for the internal display because restoring UI-scale doesn't register the
457 // restored mode to |display_mode_|, so it needs to look up the mode whose 460 // restored mode to |display_mode_|, so it needs to look up the mode whose
458 // UI-scale value matches. See the TODO in RegisterDisplayProperty(). 461 // UI-scale value matches. See the TODO in RegisterDisplayProperty().
459 const DisplayInfo& info = GetDisplayInfo(display_id); 462 const ui::ManagedDisplayInfo& info = GetDisplayInfo(display_id);
460 463
461 for (auto& mode : info.display_modes()) { 464 for (auto& mode : info.display_modes()) {
462 if (GetDisplayIdForUIScaling() == display_id) { 465 if (GetDisplayIdForUIScaling() == display_id) {
463 if (info.configured_ui_scale() == mode->ui_scale()) 466 if (info.configured_ui_scale() == mode->ui_scale())
464 return mode.get(); 467 return mode.get();
465 } else if (mode->native()) { 468 } else if (mode->native()) {
466 return mode.get(); 469 return mode.get();
467 } 470 }
468 } 471 }
469 return selected_mode; 472 return selected_mode;
470 } 473 }
471 474
472 void DisplayManager::RegisterDisplayRotationProperties( 475 void DisplayManager::RegisterDisplayRotationProperties(
473 bool rotation_lock, 476 bool rotation_lock,
474 display::Display::Rotation rotation) { 477 display::Display::Rotation rotation) {
475 if (delegate_) 478 if (delegate_)
476 delegate_->PreDisplayConfigurationChange(false); 479 delegate_->PreDisplayConfigurationChange(false);
477 registered_internal_display_rotation_lock_ = rotation_lock; 480 registered_internal_display_rotation_lock_ = rotation_lock;
478 registered_internal_display_rotation_ = rotation; 481 registered_internal_display_rotation_ = rotation;
479 if (delegate_) 482 if (delegate_)
480 delegate_->PostDisplayConfigurationChange(); 483 delegate_->PostDisplayConfigurationChange();
481 } 484 }
482 485
483 scoped_refptr<ManagedDisplayMode> DisplayManager::GetSelectedModeForDisplayId( 486 scoped_refptr<ui::ManagedDisplayMode>
484 int64_t id) const { 487 DisplayManager::GetSelectedModeForDisplayId(int64_t id) const {
485 std::map<int64_t, scoped_refptr<ManagedDisplayMode>>::const_iterator iter = 488 std::map<int64_t, scoped_refptr<ui::ManagedDisplayMode>>::const_iterator
486 display_modes_.find(id); 489 iter = display_modes_.find(id);
487 if (iter == display_modes_.end()) 490 if (iter == display_modes_.end())
488 return scoped_refptr<ManagedDisplayMode>(); 491 return scoped_refptr<ui::ManagedDisplayMode>();
489 return iter->second; 492 return iter->second;
490 } 493 }
491 494
492 bool DisplayManager::IsDisplayUIScalingEnabled() const { 495 bool DisplayManager::IsDisplayUIScalingEnabled() const {
493 return GetDisplayIdForUIScaling() != display::Display::kInvalidDisplayID; 496 return GetDisplayIdForUIScaling() != display::Display::kInvalidDisplayID;
494 } 497 }
495 498
496 gfx::Insets DisplayManager::GetOverscanInsets(int64_t display_id) const { 499 gfx::Insets DisplayManager::GetOverscanInsets(int64_t display_id) const {
497 std::map<int64_t, DisplayInfo>::const_iterator it = 500 std::map<int64_t, ui::ManagedDisplayInfo>::const_iterator it =
498 display_info_.find(display_id); 501 display_info_.find(display_id);
499 return (it != display_info_.end()) ? it->second.overscan_insets_in_dip() 502 return (it != display_info_.end()) ? it->second.overscan_insets_in_dip()
500 : gfx::Insets(); 503 : gfx::Insets();
501 } 504 }
502 505
503 void DisplayManager::SetColorCalibrationProfile( 506 void DisplayManager::SetColorCalibrationProfile(
504 int64_t display_id, 507 int64_t display_id,
505 ui::ColorCalibrationProfile profile) { 508 ui::ColorCalibrationProfile profile) {
506 #if defined(OS_CHROMEOS) 509 #if defined(OS_CHROMEOS)
507 if (!display_info_[display_id].IsColorProfileAvailable(profile)) 510 if (!display_info_[display_id].IsColorProfileAvailable(profile))
508 return; 511 return;
509 512
510 if (delegate_) 513 if (delegate_)
511 delegate_->PreDisplayConfigurationChange(false); 514 delegate_->PreDisplayConfigurationChange(false);
512 // Just sets color profile if it's not running on ChromeOS (like tests). 515 // Just sets color profile if it's not running on ChromeOS (like tests).
513 if (!base::SysInfo::IsRunningOnChromeOS() || 516 if (!base::SysInfo::IsRunningOnChromeOS() ||
514 Shell::GetInstance()->display_configurator()->SetColorCalibrationProfile( 517 Shell::GetInstance()->display_configurator()->SetColorCalibrationProfile(
515 display_id, profile)) { 518 display_id, profile)) {
516 display_info_[display_id].SetColorProfile(profile); 519 display_info_[display_id].SetColorProfile(profile);
517 UMA_HISTOGRAM_ENUMERATION("ChromeOS.Display.ColorProfile", profile, 520 UMA_HISTOGRAM_ENUMERATION("ChromeOS.Display.ColorProfile", profile,
518 ui::NUM_COLOR_PROFILES); 521 ui::NUM_COLOR_PROFILES);
519 } 522 }
520 if (delegate_) 523 if (delegate_)
521 delegate_->PostDisplayConfigurationChange(); 524 delegate_->PostDisplayConfigurationChange();
522 #endif 525 #endif
523 } 526 }
524 527
525 void DisplayManager::OnNativeDisplaysChanged( 528 void DisplayManager::OnNativeDisplaysChanged(
526 const std::vector<DisplayInfo>& updated_displays) { 529 const DisplayInfoList& updated_displays) {
527 if (updated_displays.empty()) { 530 if (updated_displays.empty()) {
528 VLOG(1) << "OnNativeDisplaysChanged(0): # of current displays=" 531 VLOG(1) << "OnNativeDisplaysChanged(0): # of current displays="
529 << active_display_list_.size(); 532 << active_display_list_.size();
530 // If the device is booted without display, or chrome is started 533 // If the device is booted without display, or chrome is started
531 // without --ash-host-window-bounds on linux desktop, use the 534 // without --ash-host-window-bounds on linux desktop, use the
532 // default display. 535 // default display.
533 if (active_display_list_.empty()) { 536 if (active_display_list_.empty()) {
534 std::vector<DisplayInfo> init_displays; 537 DisplayInfoList init_displays;
535 init_displays.push_back(DisplayInfo::CreateFromSpec(std::string())); 538 init_displays.push_back(
539 ui::ManagedDisplayInfo::CreateFromSpec(std::string()));
536 MaybeInitInternalDisplay(&init_displays[0]); 540 MaybeInitInternalDisplay(&init_displays[0]);
537 OnNativeDisplaysChanged(init_displays); 541 OnNativeDisplaysChanged(init_displays);
538 } else { 542 } else {
539 // Otherwise don't update the displays when all displays are disconnected. 543 // Otherwise don't update the displays when all displays are disconnected.
540 // This happens when: 544 // This happens when:
541 // - the device is idle and powerd requested to turn off all displays. 545 // - the device is idle and powerd requested to turn off all displays.
542 // - the device is suspended. (kernel turns off all displays) 546 // - the device is suspended. (kernel turns off all displays)
543 // - the internal display's brightness is set to 0 and no external 547 // - the internal display's brightness is set to 0 and no external
544 // display is connected. 548 // display is connected.
545 // - the internal display's brightness is 0 and external display is 549 // - the internal display's brightness is 0 and external display is
(...skipping 27 matching lines...) Expand all
573 // Mirrored monitors have the same origins. 577 // Mirrored monitors have the same origins.
574 gfx::Point origin = iter->bounds_in_native().origin(); 578 gfx::Point origin = iter->bounds_in_native().origin();
575 if (origins.find(origin) != origins.end()) { 579 if (origins.find(origin) != origins.end()) {
576 InsertAndUpdateDisplayInfo(*iter); 580 InsertAndUpdateDisplayInfo(*iter);
577 mirroring_display_id_ = iter->id(); 581 mirroring_display_id_ = iter->id();
578 } else { 582 } else {
579 origins.insert(origin); 583 origins.insert(origin);
580 new_display_info_list.push_back(*iter); 584 new_display_info_list.push_back(*iter);
581 } 585 }
582 586
583 scoped_refptr<ManagedDisplayMode> new_mode(new ManagedDisplayMode( 587 scoped_refptr<ui::ManagedDisplayMode> new_mode(new ui::ManagedDisplayMode(
584 iter->bounds_in_native().size(), 0.0 /* refresh rate */, 588 iter->bounds_in_native().size(), 0.0 /* refresh rate */,
585 false /* interlaced */, false /* native */, iter->configured_ui_scale(), 589 false /* interlaced */, false /* native */, iter->configured_ui_scale(),
586 iter->device_scale_factor())); 590 iter->device_scale_factor()));
587 const DisplayInfo::ManagedDisplayModeList& display_modes = 591 const ui::ManagedDisplayInfo::ManagedDisplayModeList& display_modes =
588 iter->display_modes(); 592 iter->display_modes();
589 // This is empty the displays are initialized from InitFromCommandLine. 593 // This is empty the displays are initialized from InitFromCommandLine.
590 if (display_modes.empty()) 594 if (display_modes.empty())
591 continue; 595 continue;
592 auto display_modes_iter = FindDisplayMode(*iter, new_mode); 596 auto display_modes_iter = FindDisplayMode(*iter, new_mode);
593 // Update the actual resolution selected as the resolution request may fail. 597 // Update the actual resolution selected as the resolution request may fail.
594 if (display_modes_iter == display_modes.end()) 598 if (display_modes_iter == display_modes.end())
595 display_modes_.erase(iter->id()); 599 display_modes_.erase(iter->id());
596 else if (display_modes_.find(iter->id()) != display_modes_.end()) 600 else if (display_modes_.find(iter->id()) != display_modes_.end())
597 display_modes_[iter->id()] = *display_modes_iter; 601 display_modes_[iter->id()] = *display_modes_iter;
598 } 602 }
599 if (display::Display::HasInternalDisplay() && !internal_display_connected) { 603 if (display::Display::HasInternalDisplay() && !internal_display_connected) {
600 if (display_info_.find(display::Display::InternalDisplayId()) == 604 if (display_info_.find(display::Display::InternalDisplayId()) ==
601 display_info_.end()) { 605 display_info_.end()) {
602 // Create a dummy internal display if the chrome restarted 606 // Create a dummy internal display if the chrome restarted
603 // in docked mode. 607 // in docked mode.
604 DisplayInfo internal_display_info( 608 ui::ManagedDisplayInfo internal_display_info(
605 display::Display::InternalDisplayId(), 609 display::Display::InternalDisplayId(),
606 l10n_util::GetStringUTF8(IDS_ASH_INTERNAL_DISPLAY_NAME), 610 l10n_util::GetStringUTF8(IDS_ASH_INTERNAL_DISPLAY_NAME),
607 false /*Internal display must not have overscan */); 611 false /*Internal display must not have overscan */);
608 internal_display_info.SetBounds(gfx::Rect(0, 0, 800, 600)); 612 internal_display_info.SetBounds(gfx::Rect(0, 0, 800, 600));
609 display_info_[display::Display::InternalDisplayId()] = 613 display_info_[display::Display::InternalDisplayId()] =
610 internal_display_info; 614 internal_display_info;
611 } else { 615 } else {
612 // Internal display is no longer active. Reset its rotation to user 616 // Internal display is no longer active. Reset its rotation to user
613 // preference, so that it is restored when the internal display becomes 617 // preference, so that it is restored when the internal display becomes
614 // active again. 618 // active again.
615 display::Display::Rotation user_rotation = 619 display::Display::Rotation user_rotation =
616 display_info_[display::Display::InternalDisplayId()].GetRotation( 620 display_info_[display::Display::InternalDisplayId()].GetRotation(
617 display::Display::ROTATION_SOURCE_USER); 621 display::Display::ROTATION_SOURCE_USER);
618 display_info_[display::Display::InternalDisplayId()].SetRotation( 622 display_info_[display::Display::InternalDisplayId()].SetRotation(
619 user_rotation, display::Display::ROTATION_SOURCE_USER); 623 user_rotation, display::Display::ROTATION_SOURCE_USER);
620 } 624 }
621 } 625 }
622 626
623 #if defined(OS_CHROMEOS) 627 #if defined(OS_CHROMEOS)
624 if (!base::SysInfo::IsRunningOnChromeOS() && 628 if (!base::SysInfo::IsRunningOnChromeOS() &&
625 new_display_info_list.size() > 1) { 629 new_display_info_list.size() > 1) {
626 display::DisplayIdList list = GenerateDisplayIdList( 630 display::DisplayIdList list = GenerateDisplayIdList(
627 new_display_info_list.begin(), new_display_info_list.end(), 631 new_display_info_list.begin(), new_display_info_list.end(),
628 [](const DisplayInfo& info) { return info.id(); }); 632 [](const ui::ManagedDisplayInfo& info) { return info.id(); });
629 633
630 const display::DisplayLayout& layout = 634 const display::DisplayLayout& layout =
631 layout_store_->GetRegisteredDisplayLayout(list); 635 layout_store_->GetRegisteredDisplayLayout(list);
632 // Mirror mode is set by DisplayConfigurator on the device. 636 // Mirror mode is set by DisplayConfigurator on the device.
633 // Emulate it when running on linux desktop. 637 // Emulate it when running on linux desktop.
634 if (layout.mirrored) 638 if (layout.mirrored)
635 SetMultiDisplayMode(MIRRORING); 639 SetMultiDisplayMode(MIRRORING);
636 } 640 }
637 #endif 641 #endif
638 642
639 UpdateDisplaysWith(new_display_info_list); 643 UpdateDisplaysWith(new_display_info_list);
640 } 644 }
641 645
642 void DisplayManager::UpdateDisplays() { 646 void DisplayManager::UpdateDisplays() {
643 DisplayInfoList display_info_list; 647 DisplayInfoList display_info_list;
644 for (const auto& display : active_display_list_) 648 for (const auto& display : active_display_list_)
645 display_info_list.push_back(GetDisplayInfo(display.id())); 649 display_info_list.push_back(GetDisplayInfo(display.id()));
646 AddMirrorDisplayInfoIfAny(&display_info_list); 650 AddMirrorDisplayInfoIfAny(&display_info_list);
647 UpdateDisplaysWith(display_info_list); 651 UpdateDisplaysWith(display_info_list);
648 } 652 }
649 653
650 void DisplayManager::UpdateDisplaysWith( 654 void DisplayManager::UpdateDisplaysWith(
651 const std::vector<DisplayInfo>& updated_display_info_list) { 655 const DisplayInfoList& updated_display_info_list) {
652 #if defined(OS_WIN) 656 #if defined(OS_WIN)
653 DCHECK_EQ(1u, updated_display_info_list.size()) 657 DCHECK_EQ(1u, updated_display_info_list.size())
654 << ": Multiple display test does not work on Windows bots. Please " 658 << ": Multiple display test does not work on Windows bots. Please "
655 "skip (don't disable) the test using SupportsMultipleDisplays()"; 659 "skip (don't disable) the test using SupportsMultipleDisplays()";
656 #endif 660 #endif
657 661
658 DisplayInfoList new_display_info_list = updated_display_info_list; 662 DisplayInfoList new_display_info_list = updated_display_info_list;
659 std::sort(active_display_list_.begin(), active_display_list_.end(), 663 std::sort(active_display_list_.begin(), active_display_list_.end(),
660 DisplaySortFunctor()); 664 DisplaySortFunctor());
661 std::sort(new_display_info_list.begin(), new_display_info_list.end(), 665 std::sort(new_display_info_list.begin(), new_display_info_list.end(),
662 DisplayInfoSortFunctor()); 666 DisplayInfoSortFunctor());
663 667
664 if (new_display_info_list.size() > 1) { 668 if (new_display_info_list.size() > 1) {
665 display::DisplayIdList list = GenerateDisplayIdList( 669 display::DisplayIdList list = GenerateDisplayIdList(
666 new_display_info_list.begin(), new_display_info_list.end(), 670 new_display_info_list.begin(), new_display_info_list.end(),
667 [](const DisplayInfo& info) { return info.id(); }); 671 [](const ui::ManagedDisplayInfo& info) { return info.id(); });
668 const display::DisplayLayout& layout = 672 const display::DisplayLayout& layout =
669 layout_store_->GetRegisteredDisplayLayout(list); 673 layout_store_->GetRegisteredDisplayLayout(list);
670 current_default_multi_display_mode_ = 674 current_default_multi_display_mode_ =
671 (layout.default_unified && unified_desktop_enabled_) ? UNIFIED 675 (layout.default_unified && unified_desktop_enabled_) ? UNIFIED
672 : EXTENDED; 676 : EXTENDED;
673 } 677 }
674 678
675 if (multi_display_mode_ != MIRRORING) 679 if (multi_display_mode_ != MIRRORING)
676 multi_display_mode_ = current_default_multi_display_mode_; 680 multi_display_mode_ = current_default_multi_display_mode_;
677 681
(...skipping 22 matching lines...) Expand all
700 CreateDisplayFromDisplayInfoById(new_info_iter->id())); 704 CreateDisplayFromDisplayInfoById(new_info_iter->id()));
701 ++new_info_iter; 705 ++new_info_iter;
702 } else if (new_info_iter == new_display_info_list.end()) { 706 } else if (new_info_iter == new_display_info_list.end()) {
703 // more displays in current list. 707 // more displays in current list.
704 removed_displays.push_back(*curr_iter); 708 removed_displays.push_back(*curr_iter);
705 ++curr_iter; 709 ++curr_iter;
706 } else if (curr_iter->id() == new_info_iter->id()) { 710 } else if (curr_iter->id() == new_info_iter->id()) {
707 const display::Display& current_display = *curr_iter; 711 const display::Display& current_display = *curr_iter;
708 // Copy the info because |InsertAndUpdateDisplayInfo| updates the 712 // Copy the info because |InsertAndUpdateDisplayInfo| updates the
709 // instance. 713 // instance.
710 const DisplayInfo current_display_info = 714 const ui::ManagedDisplayInfo current_display_info =
711 GetDisplayInfo(current_display.id()); 715 GetDisplayInfo(current_display.id());
712 InsertAndUpdateDisplayInfo(*new_info_iter); 716 InsertAndUpdateDisplayInfo(*new_info_iter);
713 display::Display new_display = 717 display::Display new_display =
714 CreateDisplayFromDisplayInfoById(new_info_iter->id()); 718 CreateDisplayFromDisplayInfoById(new_info_iter->id());
715 const DisplayInfo& new_display_info = GetDisplayInfo(new_display.id()); 719 const ui::ManagedDisplayInfo& new_display_info =
720 GetDisplayInfo(new_display.id());
716 721
717 uint32_t metrics = display::DisplayObserver::DISPLAY_METRIC_NONE; 722 uint32_t metrics = display::DisplayObserver::DISPLAY_METRIC_NONE;
718 723
719 // At that point the new Display objects we have are not entirely updated, 724 // At that point the new Display objects we have are not entirely updated,
720 // they are missing the translation related to the Display disposition in 725 // they are missing the translation related to the Display disposition in
721 // the layout. 726 // the layout.
722 // Using display.bounds() and display.work_area() would fail most of the 727 // Using display.bounds() and display.work_area() would fail most of the
723 // time. 728 // time.
724 if (force_bounds_changed_ || (current_display_info.bounds_in_native() != 729 if (force_bounds_changed_ || (current_display_info.bounds_in_native() !=
725 new_display_info.bounds_in_native()) || 730 new_display_info.bounds_in_native()) ||
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
891 // info in hardware mirroring comes from DisplayConfigurator. 896 // info in hardware mirroring comes from DisplayConfigurator.
892 if (!IsInMirrorMode()) 897 if (!IsInMirrorMode())
893 ReconfigureDisplays(); 898 ReconfigureDisplays();
894 } 899 }
895 900
896 bool DisplayManager::IsInUnifiedMode() const { 901 bool DisplayManager::IsInUnifiedMode() const {
897 return multi_display_mode_ == UNIFIED && 902 return multi_display_mode_ == UNIFIED &&
898 !software_mirroring_display_list_.empty(); 903 !software_mirroring_display_list_.empty();
899 } 904 }
900 905
901 const DisplayInfo& DisplayManager::GetDisplayInfo(int64_t display_id) const { 906 const ui::ManagedDisplayInfo& DisplayManager::GetDisplayInfo(
907 int64_t display_id) const {
902 DCHECK_NE(display::Display::kInvalidDisplayID, display_id); 908 DCHECK_NE(display::Display::kInvalidDisplayID, display_id);
903 909
904 std::map<int64_t, DisplayInfo>::const_iterator iter = 910 std::map<int64_t, ui::ManagedDisplayInfo>::const_iterator iter =
905 display_info_.find(display_id); 911 display_info_.find(display_id);
906 CHECK(iter != display_info_.end()) << display_id; 912 CHECK(iter != display_info_.end()) << display_id;
907 return iter->second; 913 return iter->second;
908 } 914 }
909 915
910 const display::Display DisplayManager::GetMirroringDisplayById( 916 const display::Display DisplayManager::GetMirroringDisplayById(
911 int64_t display_id) const { 917 int64_t display_id) const {
912 auto iter = std::find_if(software_mirroring_display_list_.begin(), 918 auto iter = std::find_if(software_mirroring_display_list_.begin(),
913 software_mirroring_display_list_.end(), 919 software_mirroring_display_list_.end(),
914 [display_id](const display::Display& display) { 920 [display_id](const display::Display& display) {
915 return display.id() == display_id; 921 return display.id() == display_id;
916 }); 922 });
917 return iter == software_mirroring_display_list_.end() ? display::Display() 923 return iter == software_mirroring_display_list_.end() ? display::Display()
918 : *iter; 924 : *iter;
919 } 925 }
920 926
921 std::string DisplayManager::GetDisplayNameForId(int64_t id) { 927 std::string DisplayManager::GetDisplayNameForId(int64_t id) {
922 if (id == display::Display::kInvalidDisplayID) 928 if (id == display::Display::kInvalidDisplayID)
923 return l10n_util::GetStringUTF8(IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME); 929 return l10n_util::GetStringUTF8(IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME);
924 930
925 std::map<int64_t, DisplayInfo>::const_iterator iter = display_info_.find(id); 931 std::map<int64_t, ui::ManagedDisplayInfo>::const_iterator iter =
932 display_info_.find(id);
926 if (iter != display_info_.end() && !iter->second.name().empty()) 933 if (iter != display_info_.end() && !iter->second.name().empty())
927 return iter->second.name(); 934 return iter->second.name();
928 935
929 return base::StringPrintf("Display %d", static_cast<int>(id)); 936 return base::StringPrintf("Display %d", static_cast<int>(id));
930 } 937 }
931 938
932 int64_t DisplayManager::GetDisplayIdForUIScaling() const { 939 int64_t DisplayManager::GetDisplayIdForUIScaling() const {
933 // UI Scaling is effective on internal display. 940 // UI Scaling is effective on internal display.
934 return display::Display::HasInternalDisplay() 941 return display::Display::HasInternalDisplay()
935 ? display::Display::InternalDisplayId() 942 ? display::Display::InternalDisplayId()
(...skipping 14 matching lines...) Expand all
950 return; 957 return;
951 } 958 }
952 #endif 959 #endif
953 multi_display_mode_ = 960 multi_display_mode_ =
954 mirror ? MIRRORING : current_default_multi_display_mode_; 961 mirror ? MIRRORING : current_default_multi_display_mode_;
955 ReconfigureDisplays(); 962 ReconfigureDisplays();
956 } 963 }
957 964
958 void DisplayManager::AddRemoveDisplay() { 965 void DisplayManager::AddRemoveDisplay() {
959 DCHECK(!active_display_list_.empty()); 966 DCHECK(!active_display_list_.empty());
960 std::vector<DisplayInfo> new_display_info_list; 967 DisplayInfoList new_display_info_list;
961 const DisplayInfo& first_display = 968 const ui::ManagedDisplayInfo& first_display =
962 IsInUnifiedMode() 969 IsInUnifiedMode()
963 ? GetDisplayInfo(software_mirroring_display_list_[0].id()) 970 ? GetDisplayInfo(software_mirroring_display_list_[0].id())
964 : GetDisplayInfo(active_display_list_[0].id()); 971 : GetDisplayInfo(active_display_list_[0].id());
965 new_display_info_list.push_back(first_display); 972 new_display_info_list.push_back(first_display);
966 // Add if there is only one display connected. 973 // Add if there is only one display connected.
967 if (num_connected_displays() == 1) { 974 if (num_connected_displays() == 1) {
968 const int kVerticalOffsetPx = 100; 975 const int kVerticalOffsetPx = 100;
969 // Layout the 2nd display below the primary as with the real device. 976 // Layout the 2nd display below the primary as with the real device.
970 gfx::Rect host_bounds = first_display.bounds_in_native(); 977 gfx::Rect host_bounds = first_display.bounds_in_native();
971 new_display_info_list.push_back( 978 new_display_info_list.push_back(
972 DisplayInfo::CreateFromSpec(base::StringPrintf( 979 ui::ManagedDisplayInfo::CreateFromSpec(base::StringPrintf(
973 "%d+%d-600x%d", host_bounds.x(), 980 "%d+%d-600x%d", host_bounds.x(),
974 host_bounds.bottom() + kVerticalOffsetPx, host_bounds.height()))); 981 host_bounds.bottom() + kVerticalOffsetPx, host_bounds.height())));
975 } 982 }
976 num_connected_displays_ = new_display_info_list.size(); 983 num_connected_displays_ = new_display_info_list.size();
977 mirroring_display_id_ = display::Display::kInvalidDisplayID; 984 mirroring_display_id_ = display::Display::kInvalidDisplayID;
978 software_mirroring_display_list_.clear(); 985 software_mirroring_display_list_.clear();
979 UpdateDisplaysWith(new_display_info_list); 986 UpdateDisplaysWith(new_display_info_list);
980 } 987 }
981 988
982 void DisplayManager::ToggleDisplayScaleFactor() { 989 void DisplayManager::ToggleDisplayScaleFactor() {
983 DCHECK(!active_display_list_.empty()); 990 DCHECK(!active_display_list_.empty());
984 std::vector<DisplayInfo> new_display_info_list; 991 DisplayInfoList new_display_info_list;
985 for (display::DisplayList::const_iterator iter = active_display_list_.begin(); 992 for (display::DisplayList::const_iterator iter = active_display_list_.begin();
986 iter != active_display_list_.end(); ++iter) { 993 iter != active_display_list_.end(); ++iter) {
987 DisplayInfo display_info = GetDisplayInfo(iter->id()); 994 ui::ManagedDisplayInfo display_info = GetDisplayInfo(iter->id());
988 display_info.set_device_scale_factor( 995 display_info.set_device_scale_factor(
989 display_info.device_scale_factor() == 1.0f ? 2.0f : 1.0f); 996 display_info.device_scale_factor() == 1.0f ? 2.0f : 1.0f);
990 new_display_info_list.push_back(display_info); 997 new_display_info_list.push_back(display_info);
991 } 998 }
992 AddMirrorDisplayInfoIfAny(&new_display_info_list); 999 AddMirrorDisplayInfoIfAny(&new_display_info_list);
993 UpdateDisplaysWith(new_display_info_list); 1000 UpdateDisplaysWith(new_display_info_list);
994 } 1001 }
995 1002
996 #if defined(OS_CHROMEOS) 1003 #if defined(OS_CHROMEOS)
997 void DisplayManager::SetSoftwareMirroring(bool enabled) { 1004 void DisplayManager::SetSoftwareMirroring(bool enabled) {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1074 void DisplayManager::CreateScreenForShutdown() const { 1081 void DisplayManager::CreateScreenForShutdown() const {
1075 delete screen_for_shutdown; 1082 delete screen_for_shutdown;
1076 screen_for_shutdown = screen_->CloneForShutdown(); 1083 screen_for_shutdown = screen_->CloneForShutdown();
1077 display::Screen::SetScreenInstance(screen_for_shutdown); 1084 display::Screen::SetScreenInstance(screen_for_shutdown);
1078 } 1085 }
1079 1086
1080 void DisplayManager::UpdateInternalManagedDisplayModeListForTest() { 1087 void DisplayManager::UpdateInternalManagedDisplayModeListForTest() {
1081 if (!display::Display::HasInternalDisplay() || 1088 if (!display::Display::HasInternalDisplay() ||
1082 display_info_.count(display::Display::InternalDisplayId()) == 0) 1089 display_info_.count(display::Display::InternalDisplayId()) == 0)
1083 return; 1090 return;
1084 DisplayInfo* info = &display_info_[display::Display::InternalDisplayId()]; 1091 ui::ManagedDisplayInfo* info =
1092 &display_info_[display::Display::InternalDisplayId()];
1085 SetInternalManagedDisplayModeList(info); 1093 SetInternalManagedDisplayModeList(info);
1086 } 1094 }
1087 1095
1088 void DisplayManager::CreateSoftwareMirroringDisplayInfo( 1096 void DisplayManager::CreateSoftwareMirroringDisplayInfo(
1089 DisplayInfoList* display_info_list) { 1097 DisplayInfoList* display_info_list) {
1090 // Use the internal display or 1st as the mirror source, then scale 1098 // Use the internal display or 1st as the mirror source, then scale
1091 // the root window so that it matches the external display's 1099 // the root window so that it matches the external display's
1092 // resolution. This is necessary in order for scaling to work while 1100 // resolution. This is necessary in order for scaling to work while
1093 // mirrored. 1101 // mirrored.
1094 switch (multi_display_mode_) { 1102 switch (multi_display_mode_) {
1095 case MIRRORING: { 1103 case MIRRORING: {
1096 if (display_info_list->size() != 2) 1104 if (display_info_list->size() != 2)
1097 return; 1105 return;
1098 bool zero_is_source = 1106 bool zero_is_source =
1099 first_display_id_ == (*display_info_list)[0].id() || 1107 first_display_id_ == (*display_info_list)[0].id() ||
1100 display::Display::IsInternalDisplayId((*display_info_list)[0].id()); 1108 display::Display::IsInternalDisplayId((*display_info_list)[0].id());
1101 DCHECK_EQ(MIRRORING, multi_display_mode_); 1109 DCHECK_EQ(MIRRORING, multi_display_mode_);
1102 mirroring_display_id_ = (*display_info_list)[zero_is_source ? 1 : 0].id(); 1110 mirroring_display_id_ = (*display_info_list)[zero_is_source ? 1 : 0].id();
1103 1111
1104 int64_t display_id = mirroring_display_id_; 1112 int64_t display_id = mirroring_display_id_;
1105 auto iter = 1113 auto iter =
1106 std::find_if(display_info_list->begin(), display_info_list->end(), 1114 std::find_if(display_info_list->begin(), display_info_list->end(),
1107 [display_id](const DisplayInfo& info) { 1115 [display_id](const ui::ManagedDisplayInfo& info) {
1108 return info.id() == display_id; 1116 return info.id() == display_id;
1109 }); 1117 });
1110 DCHECK(iter != display_info_list->end()); 1118 DCHECK(iter != display_info_list->end());
1111 1119
1112 DisplayInfo info = *iter; 1120 ui::ManagedDisplayInfo info = *iter;
1113 info.SetOverscanInsets(gfx::Insets()); 1121 info.SetOverscanInsets(gfx::Insets());
1114 InsertAndUpdateDisplayInfo(info); 1122 InsertAndUpdateDisplayInfo(info);
1115 software_mirroring_display_list_.push_back( 1123 software_mirroring_display_list_.push_back(
1116 CreateMirroringDisplayFromDisplayInfoById(mirroring_display_id_, 1124 CreateMirroringDisplayFromDisplayInfoById(mirroring_display_id_,
1117 gfx::Point(), 1.0f)); 1125 gfx::Point(), 1.0f));
1118 display_info_list->erase(iter); 1126 display_info_list->erase(iter);
1119 break; 1127 break;
1120 } 1128 }
1121 case UNIFIED: { 1129 case UNIFIED: {
1122 if (display_info_list->size() == 1) 1130 if (display_info_list->size() == 1)
(...skipping 10 matching lines...) Expand all
1133 float default_device_scale_factor = 1.0f; 1141 float default_device_scale_factor = 1.0f;
1134 for (auto& info : *display_info_list) { 1142 for (auto& info : *display_info_list) {
1135 max_height = std::max(max_height, info.size_in_pixel().height()); 1143 max_height = std::max(max_height, info.size_in_pixel().height());
1136 if (!default_height || 1144 if (!default_height ||
1137 display::Display::IsInternalDisplayId(info.id())) { 1145 display::Display::IsInternalDisplayId(info.id())) {
1138 default_height = info.size_in_pixel().height(); 1146 default_height = info.size_in_pixel().height();
1139 default_device_scale_factor = info.device_scale_factor(); 1147 default_device_scale_factor = info.device_scale_factor();
1140 } 1148 }
1141 } 1149 }
1142 1150
1143 DisplayInfo::ManagedDisplayModeList display_mode_list; 1151 ui::ManagedDisplayInfo::ManagedDisplayModeList display_mode_list;
1144 std::set<std::pair<float, float>> dsf_scale_list; 1152 std::set<std::pair<float, float>> dsf_scale_list;
1145 1153
1146 // 2nd Pass. Compute the unified display size. 1154 // 2nd Pass. Compute the unified display size.
1147 for (auto& info : *display_info_list) { 1155 for (auto& info : *display_info_list) {
1148 InsertAndUpdateDisplayInfo(info); 1156 InsertAndUpdateDisplayInfo(info);
1149 gfx::Point origin(unified_bounds.right(), 0); 1157 gfx::Point origin(unified_bounds.right(), 0);
1150 float scale = 1158 float scale =
1151 info.size_in_pixel().height() / static_cast<float>(max_height); 1159 info.size_in_pixel().height() / static_cast<float>(max_height);
1152 // The display is scaled to fit the unified desktop size. 1160 // The display is scaled to fit the unified desktop size.
1153 display::Display display = CreateMirroringDisplayFromDisplayInfoById( 1161 display::Display display = CreateMirroringDisplayFromDisplayInfoById(
1154 info.id(), origin, 1.0f / scale); 1162 info.id(), origin, 1.0f / scale);
1155 unified_bounds.Union(display.bounds()); 1163 unified_bounds.Union(display.bounds());
1156 1164
1157 dsf_scale_list.insert( 1165 dsf_scale_list.insert(
1158 std::make_pair(info.device_scale_factor(), scale)); 1166 std::make_pair(info.device_scale_factor(), scale));
1159 } 1167 }
1160 1168
1161 DisplayInfo info(kUnifiedDisplayId, "Unified Desktop", false); 1169 ui::ManagedDisplayInfo info(kUnifiedDisplayId, "Unified Desktop", false);
1162 1170
1163 scoped_refptr<ManagedDisplayMode> native_mode(new ManagedDisplayMode( 1171 scoped_refptr<ui::ManagedDisplayMode> native_mode(
1164 unified_bounds.size(), 60.0f, false, true, 1.0, 1.0)); 1172 new ui::ManagedDisplayMode(unified_bounds.size(), 60.0f, false, true,
1165 DisplayInfo::ManagedDisplayModeList modes = 1173 1.0, 1.0));
1174 ui::ManagedDisplayInfo::ManagedDisplayModeList modes =
1166 CreateUnifiedManagedDisplayModeList(native_mode, dsf_scale_list); 1175 CreateUnifiedManagedDisplayModeList(native_mode, dsf_scale_list);
1167 1176
1168 // Find the default mode. 1177 // Find the default mode.
1169 auto iter = std::find_if( 1178 auto iter = std::find_if(
1170 modes.begin(), modes.end(), 1179 modes.begin(), modes.end(),
1171 [default_height, default_device_scale_factor]( 1180 [default_height, default_device_scale_factor](
1172 const scoped_refptr<ManagedDisplayMode>& mode) { 1181 const scoped_refptr<ui::ManagedDisplayMode>& mode) {
1173 return mode->size().height() == default_height && 1182 return mode->size().height() == default_height &&
1174 mode->device_scale_factor() == default_device_scale_factor; 1183 mode->device_scale_factor() == default_device_scale_factor;
1175 }); 1184 });
1176 1185
1177 scoped_refptr<ManagedDisplayMode> dm(*iter); 1186 scoped_refptr<ui::ManagedDisplayMode> dm(*iter);
1178 *iter = make_scoped_refptr(new ManagedDisplayMode( 1187 *iter = make_scoped_refptr(new ui::ManagedDisplayMode(
1179 dm->size(), dm->refresh_rate(), dm->is_interlaced(), 1188 dm->size(), dm->refresh_rate(), dm->is_interlaced(),
1180 true /* native */, dm->ui_scale(), dm->device_scale_factor())); 1189 true /* native */, dm->ui_scale(), dm->device_scale_factor()));
1181 1190
1182 info.SetManagedDisplayModes(modes); 1191 info.SetManagedDisplayModes(modes);
1183 info.set_device_scale_factor(dm->device_scale_factor()); 1192 info.set_device_scale_factor(dm->device_scale_factor());
1184 info.SetBounds(gfx::Rect(dm->size())); 1193 info.SetBounds(gfx::Rect(dm->size()));
1185 1194
1186 // Forget the configured resolution if the original unified 1195 // Forget the configured resolution if the original unified
1187 // desktop resolution has changed. 1196 // desktop resolution has changed.
1188 if (display_info_.count(kUnifiedDisplayId) != 0 && 1197 if (display_info_.count(kUnifiedDisplayId) != 0 &&
1189 GetMaxNativeSize(display_info_[kUnifiedDisplayId]) != 1198 GetMaxNativeSize(display_info_[kUnifiedDisplayId]) !=
1190 unified_bounds.size()) { 1199 unified_bounds.size()) {
1191 display_modes_.erase(kUnifiedDisplayId); 1200 display_modes_.erase(kUnifiedDisplayId);
1192 } 1201 }
1193 1202
1194 // 3rd Pass. Set the selected mode, then recompute the mirroring 1203 // 3rd Pass. Set the selected mode, then recompute the mirroring
1195 // display size. 1204 // display size.
1196 scoped_refptr<ManagedDisplayMode> mode = 1205 scoped_refptr<ui::ManagedDisplayMode> mode =
1197 GetSelectedModeForDisplayId(kUnifiedDisplayId); 1206 GetSelectedModeForDisplayId(kUnifiedDisplayId);
1198 if (mode && FindDisplayMode(info, mode) != info.display_modes().end()) { 1207 if (mode && FindDisplayMode(info, mode) != info.display_modes().end()) {
1199 info.set_device_scale_factor(mode->device_scale_factor()); 1208 info.set_device_scale_factor(mode->device_scale_factor());
1200 info.SetBounds(gfx::Rect(mode->size())); 1209 info.SetBounds(gfx::Rect(mode->size()));
1201 } else { 1210 } else {
1202 display_modes_.erase(kUnifiedDisplayId); 1211 display_modes_.erase(kUnifiedDisplayId);
1203 } 1212 }
1204 1213
1205 int unified_display_height = info.size_in_pixel().height(); 1214 int unified_display_height = info.size_in_pixel().height();
1206 gfx::Point origin; 1215 gfx::Point origin;
(...skipping 24 matching lines...) Expand all
1231 if (iter != active_display_list_.end()) 1240 if (iter != active_display_list_.end())
1232 return &(*iter); 1241 return &(*iter);
1233 // TODO(oshima): This happens when windows in unified desktop have 1242 // TODO(oshima): This happens when windows in unified desktop have
1234 // been moved to a normal window. Fix this. 1243 // been moved to a normal window. Fix this.
1235 if (id != kUnifiedDisplayId) 1244 if (id != kUnifiedDisplayId)
1236 DLOG(WARNING) << "Could not find display:" << id; 1245 DLOG(WARNING) << "Could not find display:" << id;
1237 return nullptr; 1246 return nullptr;
1238 } 1247 }
1239 1248
1240 void DisplayManager::AddMirrorDisplayInfoIfAny( 1249 void DisplayManager::AddMirrorDisplayInfoIfAny(
1241 std::vector<DisplayInfo>* display_info_list) { 1250 DisplayInfoList* display_info_list) {
1242 if (software_mirroring_enabled() && IsInMirrorMode()) { 1251 if (software_mirroring_enabled() && IsInMirrorMode()) {
1243 display_info_list->push_back(GetDisplayInfo(mirroring_display_id_)); 1252 display_info_list->push_back(GetDisplayInfo(mirroring_display_id_));
1244 software_mirroring_display_list_.clear(); 1253 software_mirroring_display_list_.clear();
1245 } 1254 }
1246 } 1255 }
1247 1256
1248 void DisplayManager::InsertAndUpdateDisplayInfo(const DisplayInfo& new_info) { 1257 void DisplayManager::InsertAndUpdateDisplayInfo(
1249 std::map<int64_t, DisplayInfo>::iterator info = 1258 const ui::ManagedDisplayInfo& new_info) {
1259 std::map<int64_t, ui::ManagedDisplayInfo>::iterator info =
1250 display_info_.find(new_info.id()); 1260 display_info_.find(new_info.id());
1251 if (info != display_info_.end()) { 1261 if (info != display_info_.end()) {
1252 info->second.Copy(new_info); 1262 info->second.Copy(new_info);
1253 } else { 1263 } else {
1254 display_info_[new_info.id()] = new_info; 1264 display_info_[new_info.id()] = new_info;
1255 display_info_[new_info.id()].set_native(false); 1265 display_info_[new_info.id()].set_native(false);
1256 // FHD with 1.25 DSF behaves differently from other configuration. 1266 // FHD with 1.25 DSF behaves differently from other configuration.
1257 // It uses 1.25 DSF only when UI-Scale is set to 0.8. 1267 // It uses 1.25 DSF only when UI-Scale is set to 0.8.
1258 // For new users, use the UI-scale to 0.8 so that it will use DSF=1.25 1268 // For new users, use the UI-scale to 0.8 so that it will use DSF=1.25
1259 // internally. 1269 // internally.
1260 if (display::Display::IsInternalDisplayId(new_info.id()) && 1270 if (display::Display::IsInternalDisplayId(new_info.id()) &&
1261 new_info.bounds_in_native().height() == 1080 && 1271 new_info.bounds_in_native().height() == 1080 &&
1262 new_info.device_scale_factor() == 1.25f) { 1272 new_info.device_scale_factor() == 1.25f) {
1263 display_info_[new_info.id()].set_configured_ui_scale(0.8f); 1273 display_info_[new_info.id()].set_configured_ui_scale(0.8f);
1264 } 1274 }
1265 } 1275 }
1266 display_info_[new_info.id()].UpdateDisplaySize(); 1276 display_info_[new_info.id()].UpdateDisplaySize();
1267 OnDisplayInfoUpdated(display_info_[new_info.id()]); 1277 OnDisplayInfoUpdated(display_info_[new_info.id()]);
1268 } 1278 }
1269 1279
1270 void DisplayManager::OnDisplayInfoUpdated(const DisplayInfo& display_info) { 1280 void DisplayManager::OnDisplayInfoUpdated(
1281 const ui::ManagedDisplayInfo& display_info) {
1271 #if defined(OS_CHROMEOS) 1282 #if defined(OS_CHROMEOS)
1272 ui::ColorCalibrationProfile color_profile = display_info.color_profile(); 1283 ui::ColorCalibrationProfile color_profile = display_info.color_profile();
1273 if (color_profile != ui::COLOR_PROFILE_STANDARD) { 1284 if (color_profile != ui::COLOR_PROFILE_STANDARD) {
1274 Shell::GetInstance()->display_configurator()->SetColorCalibrationProfile( 1285 Shell::GetInstance()->display_configurator()->SetColorCalibrationProfile(
1275 display_info.id(), color_profile); 1286 display_info.id(), color_profile);
1276 } 1287 }
1277 #endif 1288 #endif
1278 } 1289 }
1279 1290
1280 display::Display DisplayManager::CreateDisplayFromDisplayInfoById(int64_t id) { 1291 display::Display DisplayManager::CreateDisplayFromDisplayInfoById(int64_t id) {
1281 DCHECK(display_info_.find(id) != display_info_.end()) << "id=" << id; 1292 DCHECK(display_info_.find(id) != display_info_.end()) << "id=" << id;
1282 const DisplayInfo& display_info = display_info_[id]; 1293 const ui::ManagedDisplayInfo& display_info = display_info_[id];
1283 1294
1284 display::Display new_display(display_info.id()); 1295 display::Display new_display(display_info.id());
1285 gfx::Rect bounds_in_native(display_info.size_in_pixel()); 1296 gfx::Rect bounds_in_native(display_info.size_in_pixel());
1286 float device_scale_factor = display_info.GetEffectiveDeviceScaleFactor(); 1297 float device_scale_factor = display_info.GetEffectiveDeviceScaleFactor();
1287 1298
1288 // Simply set the origin to (0,0). The primary display's origin is 1299 // Simply set the origin to (0,0). The primary display's origin is
1289 // always (0,0) and the bounds of non-primary display(s) will be updated 1300 // always (0,0) and the bounds of non-primary display(s) will be updated
1290 // in |UpdateNonPrimaryDisplayBoundsForLayout| called in |UpdateDisplay|. 1301 // in |UpdateNonPrimaryDisplayBoundsForLayout| called in |UpdateDisplay|.
1291 new_display.SetScaleAndBounds(device_scale_factor, 1302 new_display.SetScaleAndBounds(device_scale_factor,
1292 gfx::Rect(bounds_in_native.size())); 1303 gfx::Rect(bounds_in_native.size()));
1293 new_display.set_rotation(display_info.GetActiveRotation()); 1304 new_display.set_rotation(display_info.GetActiveRotation());
1294 new_display.set_touch_support(display_info.touch_support()); 1305 new_display.set_touch_support(display_info.touch_support());
1295 new_display.set_maximum_cursor_size(display_info.maximum_cursor_size()); 1306 new_display.set_maximum_cursor_size(display_info.maximum_cursor_size());
1296 return new_display; 1307 return new_display;
1297 } 1308 }
1298 1309
1299 display::Display DisplayManager::CreateMirroringDisplayFromDisplayInfoById( 1310 display::Display DisplayManager::CreateMirroringDisplayFromDisplayInfoById(
1300 int64_t id, 1311 int64_t id,
1301 const gfx::Point& origin, 1312 const gfx::Point& origin,
1302 float scale) { 1313 float scale) {
1303 DCHECK(display_info_.find(id) != display_info_.end()) << "id=" << id; 1314 DCHECK(display_info_.find(id) != display_info_.end()) << "id=" << id;
1304 const DisplayInfo& display_info = display_info_[id]; 1315 const ui::ManagedDisplayInfo& display_info = display_info_[id];
1305 1316
1306 display::Display new_display(display_info.id()); 1317 display::Display new_display(display_info.id());
1307 new_display.SetScaleAndBounds( 1318 new_display.SetScaleAndBounds(
1308 1.0f, gfx::Rect(origin, gfx::ScaleToFlooredSize( 1319 1.0f, gfx::Rect(origin, gfx::ScaleToFlooredSize(
1309 display_info.size_in_pixel(), scale))); 1320 display_info.size_in_pixel(), scale)));
1310 new_display.set_touch_support(display_info.touch_support()); 1321 new_display.set_touch_support(display_info.touch_support());
1311 new_display.set_maximum_cursor_size(display_info.maximum_cursor_size()); 1322 new_display.set_maximum_cursor_size(display_info.maximum_cursor_size());
1312 return new_display; 1323 return new_display;
1313 } 1324 }
1314 1325
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1355 layout.ApplyToDisplayList(display_list, updated_ids, 1366 layout.ApplyToDisplayList(display_list, updated_ids,
1356 kMinimumOverlapForInvalidOffset); 1367 kMinimumOverlapForInvalidOffset);
1357 } 1368 }
1358 1369
1359 void DisplayManager::RunPendingTasksForTest() { 1370 void DisplayManager::RunPendingTasksForTest() {
1360 if (!software_mirroring_display_list_.empty()) 1371 if (!software_mirroring_display_list_.empty())
1361 base::RunLoop().RunUntilIdle(); 1372 base::RunLoop().RunUntilIdle();
1362 } 1373 }
1363 1374
1364 } // namespace ash 1375 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698