display_manager.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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 3// found in the LICENSE file. 4 5#include "ash/display/display_manager.h" 6 7#include <cmath> 8#include <set> 9#include <string> 10#include <vector> 11 12#include "ash/ash_switches.h" 13#include "ash/display/display_controller.h" 14#include "ash/screen_ash.h" 15#include "ash/shell.h" 16#include "base/auto_reset.h" 17#include "base/command_line.h" 18#include "base/logging.h" 19#include "base/stl_util.h" 20#include "base/stringprintf.h" 21#include "base/strings/string_number_conversions.h" 22#include "base/strings/string_split.h" 23#include "base/utf_string_conversions.h" 24#include "grit/ash_strings.h" 25#include "ui/aura/client/screen_position_client.h" 26#include "ui/aura/env.h" 27#include "ui/aura/root_window.h" 28#include "ui/aura/root_window_host.h" 29#include "ui/aura/window_property.h" 30#include "ui/base/l10n/l10n_util.h" 31#include "ui/gfx/display.h" 32#include "ui/gfx/rect.h" 33#include "ui/gfx/screen.h" 34#include "ui/gfx/size_conversions.h" 35 36#if defined(USE_X11) 37#include "ui/base/x/x11_util.h" 38#endif 39 40#if defined(OS_CHROMEOS) 41#include "base/chromeos/chromeos_version.h" 42#endif 43 44#if defined(OS_WIN) 45#include "base/win/windows_version.h" 46#include "ui/aura/remote_root_window_host_win.h" 47#endif 48 49DECLARE_WINDOW_PROPERTY_TYPE(int64); 50 51namespace ash { 52namespace internal { 53typedef std::vector<gfx::Display> DisplayList; 54typedef std::vector<DisplayInfo> DisplayInfoList; 55 56namespace { 57 58// List of value UI Scale values. Scales for 2x are equivalent to 640, 59// 800, 1024, 1280, 1440, 1600 and 1920 pixel width respectively on 60// 2560 pixel width 2x density display. Please see crbug.com/233375 61// for the full list of resolutions. 62const float kUIScalesFor2x[] = {0.5f, 0.625f, 0.8f, 1.0f, 1.125f, 1.25f, 1.5f}; 63const float kUIScalesFor1280[] = {0.5f, 0.625f, 0.8f, 1.0f, 1.125f }; 64const float kUIScalesFor1366[] = {0.5f, 0.6f, 0.75f, 1.0f, 1.125f }; 65 66struct DisplaySortFunctor { 67 bool operator()(const gfx::Display& a, const gfx::Display& b) { 68 return a.id() < b.id(); 69 } 70}; 71 72struct DisplayInfoSortFunctor { 73 bool operator()(const DisplayInfo& a, const DisplayInfo& b) { 74 return a.id() < b.id(); 75 } 76}; 77 78struct ScaleComparator { 79 ScaleComparator(float s) : scale(s) {} 80 81 bool operator()(float s) const { 82 const float kEpsilon = 0.0001f; 83 return std::abs(scale - s) < kEpsilon; 84 } 85 float scale; 86}; 87 88std::vector<float> GetScalesForDisplay(const DisplayInfo& info) { 89 std::vector<float> ret; 90 if (info.device_scale_factor() == 2.0f) { 91 ret.assign(kUIScalesFor2x, kUIScalesFor2x + arraysize(kUIScalesFor2x)); 92 return ret; 93 } 94 switch (info.bounds_in_pixel().width()) { 95 case 1280: 96 ret.assign(kUIScalesFor1280, 97 kUIScalesFor1280 + arraysize(kUIScalesFor1280)); 98 break; 99 case 1366: 100 ret.assign(kUIScalesFor1366, 101 kUIScalesFor1366 + arraysize(kUIScalesFor1366)); 102 break; 103 default: 104 ret.assign(kUIScalesFor1280, 105 kUIScalesFor1280 + arraysize(kUIScalesFor1280)); 106#if defined(OS_CHROMEOS) 107 if (base::chromeos::IsRunningOnChromeOS()) 108 NOTREACHED() << "Unknown resolution:" << info.ToString(); 109#endif 110 } 111 return ret; 112} 113 114gfx::Display& GetInvalidDisplay() { 115 static gfx::Display* invalid_display = new gfx::Display(); 116 return *invalid_display; 117} 118 119} // namespace 120 121using aura::RootWindow; 122using aura::Window; 123using std::string; 124using std::vector; 125 126DEFINE_WINDOW_PROPERTY_KEY(int64, kDisplayIdKey, 127 gfx::Display::kInvalidDisplayID); 128 129DisplayManager::DisplayManager() 130 : first_display_id_(gfx::Display::kInvalidDisplayID), 131 mirrored_display_id_(gfx::Display::kInvalidDisplayID), 132 num_connected_displays_(0), 133 force_bounds_changed_(false), 134 change_display_upon_host_resize_(false) { 135#if defined(OS_CHROMEOS) 136 change_display_upon_host_resize_ = !base::chromeos::IsRunningOnChromeOS(); 137#endif 138 Init(); 139} 140 141DisplayManager::~DisplayManager() { 142} 143 144// static 145void DisplayManager::CycleDisplay() { 146 Shell::GetInstance()->display_manager()->CycleDisplayImpl(); 147} 148 149// static 150void DisplayManager::ToggleDisplayScaleFactor() { 151 Shell::GetInstance()->display_manager()->ScaleDisplayImpl(); 152} 153 154// static 155float DisplayManager::GetNextUIScale(const DisplayInfo& info, bool up) { 156 float scale = info.ui_scale(); 157 std::vector<float> scales = GetScalesForDisplay(info); 158 for (size_t i = 0; i < scales.size(); ++i) { 159 if (ScaleComparator(scales[i])(scale)) { 160 if (up && i != scales.size() - 1) 161 return scales[i + 1]; 162 if (!up && i != 0) 163 return scales[i - 1]; 164 return scales[i]; 165 } 166 } 167 // Fallback to 1.0f if the |scale| wasn't in the list. 168 return 1.0f; 169} 170 171bool DisplayManager::IsActiveDisplay(const gfx::Display& display) const { 172 for (DisplayList::const_iterator iter = displays_.begin(); 173 iter != displays_.end(); ++iter) { 174 if ((*iter).id() == display.id()) 175 return true; 176 } 177 return false; 178} 179 180bool DisplayManager::HasInternalDisplay() const { 181 return gfx::Display::InternalDisplayId() != gfx::Display::kInvalidDisplayID; 182} 183 184bool DisplayManager::IsInternalDisplayId(int64 id) const { 185 return gfx::Display::InternalDisplayId() == id; 186} 187 188bool DisplayManager::UpdateWorkAreaOfDisplayNearestWindow( 189 const aura::Window* window, 190 const gfx::Insets& insets) { 191 const RootWindow* root = window->GetRootWindow(); 192 gfx::Display& display = FindDisplayForRootWindow(root); 193 gfx::Rect old_work_area = display.work_area(); 194 display.UpdateWorkAreaFromInsets(insets); 195 return old_work_area != display.work_area(); 196} 197 198const gfx::Display& DisplayManager::GetDisplayForId(int64 id) const { 199 return const_cast<DisplayManager*>(this)->FindDisplayForId(id); 200} 201 202const gfx::Display& DisplayManager::FindDisplayContainingPoint( 203 const gfx::Point& point_in_screen) const { 204 for (DisplayList::const_iterator iter = displays_.begin(); 205 iter != displays_.end(); ++iter) { 206 const gfx::Display& display = *iter; 207 if (display.bounds().Contains(point_in_screen)) 208 return display; 209 } 210 return GetInvalidDisplay(); 211} 212 213void DisplayManager::SetOverscanInsets(int64 display_id, 214 const gfx::Insets& insets_in_dip) { 215 // TODO(oshima): insets has to be rotated according to the 216 // the current display rotation. 217 display_info_[display_id].SetOverscanInsets(true, insets_in_dip); 218 DisplayInfoList display_info_list; 219 for (DisplayList::const_iterator iter = displays_.begin(); 220 iter != displays_.end(); ++iter) { 221 display_info_list.push_back(GetDisplayInfo(iter->id())); 222 } 223 UpdateDisplays(display_info_list); 224} 225 226void DisplayManager::ClearCustomOverscanInsets(int64 display_id) { 227 display_info_[display_id].clear_has_custom_overscan_insets(); 228 DisplayInfoList display_info_list; 229 for (DisplayList::const_iterator iter = displays_.begin(); 230 iter != displays_.end(); ++iter) { 231 display_info_list.push_back(GetDisplayInfo(iter->id())); 232 } 233 UpdateDisplays(display_info_list); 234} 235 236void DisplayManager::SetDisplayRotation(int64 display_id, 237 gfx::Display::Rotation rotation) { 238 if (!IsDisplayRotationEnabled()) 239 return; 240 DisplayInfoList display_info_list; 241 for (DisplayList::const_iterator iter = displays_.begin(); 242 iter != displays_.end(); ++iter) { 243 DisplayInfo info = GetDisplayInfo(iter->id()); 244 if (info.id() == display_id) { 245 if (info.rotation() == rotation) 246 return; 247 info.set_rotation(rotation); 248 } 249 display_info_list.push_back(info); 250 } 251 UpdateDisplays(display_info_list); 252} 253 254void DisplayManager::SetDisplayUIScale(int64 display_id, 255 float ui_scale) { 256 if (!IsDisplayUIScalingEnabled() || 257 gfx::Display::InternalDisplayId() != display_id) { 258 return; 259 } 260 261 DisplayInfoList display_info_list; 262 for (DisplayList::const_iterator iter = displays_.begin(); 263 iter != displays_.end(); ++iter) { 264 DisplayInfo info = GetDisplayInfo(iter->id()); 265 if (info.id() == display_id) { 266 if (info.ui_scale() == ui_scale) 267 return; 268 std::vector<float> scales = GetScalesForDisplay(info); 269 ScaleComparator comparator(ui_scale); 270 if (std::find_if(scales.begin(), scales.end(), comparator) == 271 scales.end()) { 272 return; 273 } 274 info.set_ui_scale(ui_scale); 275 } 276 display_info_list.push_back(info); 277 } 278 UpdateDisplays(display_info_list); 279} 280 281void DisplayManager::RegisterDisplayProperty( 282 int64 display_id, 283 gfx::Display::Rotation rotation, 284 float ui_scale, 285 const gfx::Insets* overscan_insets) { 286 if (display_info_.find(display_id) == display_info_.end()) { 287 display_info_[display_id] = 288 DisplayInfo(display_id, std::string(""), false); 289 } 290 291 display_info_[display_id].set_rotation(rotation); 292 // Just in case the preference file was corrupted. 293 if (0.5f <= ui_scale && ui_scale <= 2.0f) 294 display_info_[display_id].set_ui_scale(ui_scale); 295 if (overscan_insets) 296 display_info_[display_id].SetOverscanInsets(true, *overscan_insets); 297} 298 299bool DisplayManager::IsDisplayRotationEnabled() const { 300 static bool enabled = !CommandLine::ForCurrentProcess()-> 301 HasSwitch(switches::kAshDisableDisplayRotation); 302 return enabled; 303} 304 305bool DisplayManager::IsDisplayUIScalingEnabled() const { 306 static bool enabled = !CommandLine::ForCurrentProcess()-> 307 HasSwitch(switches::kAshDisableUIScaling); 308 if (!enabled) 309 return false; 310 return GetDisplayIdForUIScaling() != gfx::Display::kInvalidDisplayID; 311} 312 313gfx::Insets DisplayManager::GetOverscanInsets(int64 display_id) const { 314 std::map<int64, DisplayInfo>::const_iterator it = 315 display_info_.find(display_id); 316 return (it != display_info_.end()) ? 317 it->second.overscan_insets_in_dip() : gfx::Insets(); 318} 319 320void DisplayManager::OnNativeDisplaysChanged( 321 const std::vector<DisplayInfo>& updated_displays) { 322 if (updated_displays.empty()) { 323 // Don't update the displays when all displays are disconnected. 324 // This happens when: 325 // - the device is idle and powerd requested to turn off all displays. 326 // - the device is suspended. (kernel turns off all displays) 327 // - the internal display's brightness is set to 0 and no external 328 // display is connected. 329 // - the internal display's brightness is 0 and external display is 330 // disconnected. 331 // The display will be updated when one of displays is turned on, and the 332 // display list will be updated correctly. 333 return; 334 } 335 first_display_id_ = updated_displays[0].id(); 336 std::set<int> y_coords; 337 if (updated_displays.size() == 1) { 338 VLOG(1) << "OnNativeDisplaysChanged(1):" << updated_displays[0].ToString(); 339 } else { 340 VLOG(1) << "OnNativeDisplaysChanged(" << updated_displays.size() 341 << ") [0]=" << updated_displays[0].ToString() 342 << ", [1]=" << updated_displays[1].ToString(); 343 } 344 345 bool internal_display_connected = false; 346 num_connected_displays_ = updated_displays.size(); 347 mirrored_display_id_ = gfx::Display::kInvalidDisplayID; 348 DisplayInfoList new_display_info_list; 349 for (DisplayInfoList::const_iterator iter = updated_displays.begin(); 350 iter != updated_displays.end(); 351 ++iter) { 352 if (!internal_display_connected) 353 internal_display_connected = IsInternalDisplayId(iter->id()); 354 // Mirrored monitors have the same y coordinates. 355 int y = iter->bounds_in_pixel().y(); 356 if (y_coords.find(y) != y_coords.end()) { 357 InsertAndUpdateDisplayInfo(*iter); 358 mirrored_display_id_ = iter->id(); 359 } else { 360 y_coords.insert(y); 361 new_display_info_list.push_back(*iter); 362 } 363 } 364 if (HasInternalDisplay() && 365 !internal_display_connected && 366 display_info_.find(gfx::Display::InternalDisplayId()) == 367 display_info_.end()) { 368 DisplayInfo internal_display_info( 369 gfx::Display::InternalDisplayId(), 370 l10n_util::GetStringUTF8(IDS_ASH_INTERNAL_DISPLAY_NAME), 371 false /*Internal display must not have overscan */); 372 internal_display_info.SetBounds(gfx::Rect(0, 0, 800, 600)); 373 display_info_[gfx::Display::InternalDisplayId()] = internal_display_info; 374 } 375 UpdateDisplays(new_display_info_list); 376} 377 378void DisplayManager::UpdateDisplays() { 379 DisplayInfoList display_info_list; 380 for (DisplayList::const_iterator iter = displays_.begin(); 381 iter != displays_.end(); ++iter) { 382 display_info_list.push_back(GetDisplayInfo(iter->id())); 383 } 384 UpdateDisplays(display_info_list); 385} 386 387void DisplayManager::UpdateDisplays( 388 const std::vector<DisplayInfo>& updated_display_info_list) { 389 DisplayInfoList new_display_info_list = updated_display_info_list; 390 std::sort(displays_.begin(), displays_.end(), DisplaySortFunctor()); 391 std::sort(new_display_info_list.begin(), 392 new_display_info_list.end(), 393 DisplayInfoSortFunctor()); 394 DisplayList removed_displays; 395 std::vector<size_t> changed_display_indices; 396 std::vector<size_t> added_display_indices; 397 398 DisplayList::iterator curr_iter = displays_.begin(); 399 DisplayInfoList::const_iterator new_info_iter = new_display_info_list.begin(); 400 401 DisplayList new_displays; 402 bool update_mouse_location = false; 403 404 while (curr_iter != displays_.end() || 405 new_info_iter != new_display_info_list.end()) { 406 if (curr_iter == displays_.end()) { 407 // more displays in new list. 408 added_display_indices.push_back(new_displays.size()); 409 InsertAndUpdateDisplayInfo(*new_info_iter); 410 new_displays.push_back( 411 CreateDisplayFromDisplayInfoById(new_info_iter->id())); 412 ++new_info_iter; 413 } else if (new_info_iter == new_display_info_list.end()) { 414 // more displays in current list. 415 removed_displays.push_back(*curr_iter); 416 ++curr_iter; 417 update_mouse_location = true; 418 } else if (curr_iter->id() == new_info_iter->id()) { 419 const gfx::Display& current_display = *curr_iter; 420 // Copy the info because |CreateDisplayFromInfo| updates the instance. 421 const DisplayInfo current_display_info = 422 GetDisplayInfo(current_display.id()); 423 InsertAndUpdateDisplayInfo(*new_info_iter); 424 gfx::Display new_display = 425 CreateDisplayFromDisplayInfoById(new_info_iter->id()); 426 const DisplayInfo& new_display_info = GetDisplayInfo(new_display.id()); 427 428 bool host_window_bounds_changed = 429 current_display_info.bounds_in_pixel() != 430 new_display_info.bounds_in_pixel(); 431 432 // TODO(oshima): Rotating square dislay doesn't work as the size 433 // won't change. This doesn't cause a problem now as there is no 434 // such display. This will be fixed by comparing the rotation as 435 // well when the rotation variable is added to gfx::Display. 436 if (force_bounds_changed_ || 437 host_window_bounds_changed || 438 (current_display.device_scale_factor() != 439 new_display.device_scale_factor()) || 440 (current_display_info.size_in_pixel() != 441 new_display.GetSizeInPixel())) { 442 443 // Don't update mouse location if the display size has 444 // changed due to rotation or zooming. 445 if (host_window_bounds_changed) 446 update_mouse_location = true; 447 448 changed_display_indices.push_back(new_displays.size()); 449 } 450 451 new_display.UpdateWorkAreaFromInsets(current_display.GetWorkAreaInsets()); 452 new_displays.push_back(new_display); 453 ++curr_iter; 454 ++new_info_iter; 455 } else if (curr_iter->id() < new_info_iter->id()) { 456 // more displays in current list between ids, which means it is deleted. 457 removed_displays.push_back(*curr_iter); 458 ++curr_iter; 459 update_mouse_location = true; 460 } else { 461 // more displays in new list between ids, which means it is added. 462 added_display_indices.push_back(new_displays.size()); 463 InsertAndUpdateDisplayInfo(*new_info_iter); 464 new_displays.push_back( 465 CreateDisplayFromDisplayInfoById(new_info_iter->id())); 466 ++new_info_iter; 467 } 468 } 469 470 // Do not update |displays_| if there's nothing to be updated. Without this, 471 // it will not update the display layout, which causes the bug 472 // http://crbug.com/155948. 473 if (changed_display_indices.empty() && added_display_indices.empty() && 474 removed_displays.empty()) { 475 return; 476 } 477 478 DisplayController* display_controller = 479 Shell::GetInstance()->display_controller(); 480 gfx::Point mouse_location_in_native; 481 display_controller->NotifyDisplayConfigurationChanging(); 482 mouse_location_in_native = display_controller->GetNativeMouseCursorLocation(); 483 484 displays_ = new_displays; 485 486 base::AutoReset<bool> resetter(&change_display_upon_host_resize_, false); 487 488 // Temporarily add displays to be removed because display object 489 // being removed are accessed during shutting down the root. 490 displays_.insert(displays_.end(), removed_displays.begin(), 491 removed_displays.end()); 492 493 for (DisplayList::const_reverse_iterator iter = removed_displays.rbegin(); 494 iter != removed_displays.rend(); ++iter) { 495 Shell::GetInstance()->screen()->NotifyDisplayRemoved(displays_.back()); 496 displays_.pop_back(); 497 } 498 for (std::vector<size_t>::iterator iter = added_display_indices.begin(); 499 iter != added_display_indices.end(); ++iter) { 500 Shell::GetInstance()->screen()->NotifyDisplayAdded(displays_[*iter]); 501 } 502 for (std::vector<size_t>::iterator iter = changed_display_indices.begin(); 503 iter != changed_display_indices.end(); ++iter) { 504 Shell::GetInstance()->screen()->NotifyBoundsChanged(displays_[*iter]); 505 } 506 display_controller->NotifyDisplayConfigurationChanged(); 507 if (update_mouse_location) 508 display_controller->EnsurePointerInDisplays(); 509 else 510 display_controller->UpdateMouseCursor(mouse_location_in_native); 511 512#if defined(USE_X11) && defined(OS_CHROMEOS) 513 if (!changed_display_indices.empty() && base::chromeos::IsRunningOnChromeOS()) 514 ui::ClearX11DefaultRootWindow(); 515#endif 516} 517 518gfx::Display* DisplayManager::GetDisplayAt(size_t index) { 519 return index < displays_.size() ? &displays_[index] : NULL; 520} 521 522const gfx::Display* DisplayManager::GetPrimaryDisplayCandidate() const { 523 const gfx::Display* primary_candidate = &displays_[0]; 524#if defined(OS_CHROMEOS) 525 if (base::chromeos::IsRunningOnChromeOS()) { 526 // On ChromeOS device, root windows are stacked vertically, and 527 // default primary is the one on top. 528 int count = GetNumDisplays(); 529 int y = GetDisplayInfo(primary_candidate->id()).bounds_in_pixel().y(); 530 for (int i = 1; i < count; ++i) { 531 const gfx::Display* display = &displays_[i]; 532 const DisplayInfo& display_info = GetDisplayInfo(display->id()); 533 if (display->IsInternal()) { 534 primary_candidate = display; 535 break; 536 } else if (display_info.bounds_in_pixel().y() < y) { 537 primary_candidate = display; 538 y = display_info.bounds_in_pixel().y(); 539 } 540 } 541 } 542#endif 543 return primary_candidate; 544} 545 546size_t DisplayManager::GetNumDisplays() const { 547 return displays_.size(); 548} 549 550bool DisplayManager::IsMirrored() const { 551 return mirrored_display_id_ != gfx::Display::kInvalidDisplayID; 552} 553 554const gfx::Display& DisplayManager::GetDisplayNearestWindow( 555 const Window* window) const { 556 if (!window) 557 return DisplayController::GetPrimaryDisplay(); 558 const RootWindow* root = window->GetRootWindow(); 559 DisplayManager* manager = const_cast<DisplayManager*>(this); 560 return root ? 561 manager->FindDisplayForRootWindow(root) : 562 DisplayController::GetPrimaryDisplay(); 563} 564 565const gfx::Display& DisplayManager::GetDisplayNearestPoint( 566 const gfx::Point& point) const { 567 // Fallback to the primary display if there is no root display containing 568 // the |point|. 569 const gfx::Display& display = FindDisplayContainingPoint(point); 570 return display.is_valid() ? display : DisplayController::GetPrimaryDisplay(); 571} 572 573const gfx::Display& DisplayManager::GetDisplayMatching( 574 const gfx::Rect& rect) const { 575 if (rect.IsEmpty()) 576 return GetDisplayNearestPoint(rect.origin()); 577 578 int max = 0; 579 const gfx::Display* matching = 0; 580 for (std::vector<gfx::Display>::const_iterator iter = displays_.begin(); 581 iter != displays_.end(); ++iter) { 582 const gfx::Display& display = *iter; 583 gfx::Rect intersect = gfx::IntersectRects(display.bounds(), rect); 584 int area = intersect.width() * intersect.height(); 585 if (area > max) { 586 max = area; 587 matching = &(*iter); 588 } 589 } 590 // Fallback to the primary display if there is no matching display. 591 return matching ? *matching : DisplayController::GetPrimaryDisplay(); 592} 593 594const DisplayInfo& DisplayManager::GetDisplayInfo(int64 display_id) const { 595 std::map<int64, DisplayInfo>::const_iterator iter = 596 display_info_.find(display_id); 597 CHECK(iter != display_info_.end()); 598 return iter->second; 599} 600 601std::string DisplayManager::GetDisplayNameForId(int64 id) { 602 if (id == gfx::Display::kInvalidDisplayID) 603 return l10n_util::GetStringUTF8(IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME); 604 605 std::map<int64, DisplayInfo>::const_iterator iter = display_info_.find(id); 606 if (iter != display_info_.end() && !iter->second.name().empty()) 607 return iter->second.name(); 608 609 return base::StringPrintf("Display %d", static_cast<int>(id)); 610} 611 612void DisplayManager::OnRootWindowResized(const aura::RootWindow* root, 613 const gfx::Size& old_size) { 614 if (change_display_upon_host_resize_) { 615 gfx::Display& display = FindDisplayForRootWindow(root); 616 gfx::Size old_display_size_in_pixel = display.GetSizeInPixel(); 617 display_info_[display.id()].SetBounds( 618 gfx::Rect(root->GetHostOrigin(), root->GetHostSize())); 619 const gfx::Size& new_root_size = root->bounds().size(); 620 if (old_size != new_root_size) { 621 display.SetSize(display_info_[display.id()].size_in_pixel()); 622 Shell::GetInstance()->screen()->NotifyBoundsChanged(display); 623 } 624 } 625} 626 627int64 DisplayManager::GetDisplayIdForUIScaling() const { 628 // UI Scaling is effective only on internal display. 629 int64 display_id = gfx::Display::InternalDisplayId(); 630#if defined(OS_WIN) 631 display_id = first_display_id(); 632#endif 633 return display_id; 634} 635 636void DisplayManager::Init() { 637 // TODO(oshima): Move this logic to DisplayChangeObserver. 638 const string size_str = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 639 switches::kAshHostWindowBounds); 640 vector<string> parts; 641 base::SplitString(size_str, ',', &parts); 642 for (vector<string>::const_iterator iter = parts.begin(); 643 iter != parts.end(); ++iter) { 644 AddDisplayFromSpec(*iter); 645 } 646 if (displays_.empty()) 647 AddDisplayFromSpec(std::string() /* default */); 648 first_display_id_ = displays_[0].id(); 649 CommandLine* command_line = CommandLine::ForCurrentProcess(); 650 if (command_line->HasSwitch(switches::kAshUseFirstDisplayAsInternal)) 651 gfx::Display::SetInternalDisplayId(first_display_id_); 652 num_connected_displays_ = displays_.size(); 653} 654 655void DisplayManager::CycleDisplayImpl() { 656 DCHECK(!displays_.empty()); 657 std::vector<DisplayInfo> new_display_info_list; 658 new_display_info_list.push_back( 659 GetDisplayInfo(DisplayController::GetPrimaryDisplay().id())); 660 // Add if there is only one display. 661 if (displays_.size() == 1) { 662 // Layout the 2nd display below the primary as with the real device. 663 aura::RootWindow* primary = Shell::GetPrimaryRootWindow(); 664 gfx::Rect host_bounds = 665 gfx::Rect(primary->GetHostOrigin(), primary->GetHostSize()); 666 new_display_info_list.push_back(DisplayInfo::CreateFromSpec( 667 base::StringPrintf( 668 "%d+%d-500x400", host_bounds.x(), host_bounds.bottom()))); 669 } 670 num_connected_displays_ = new_display_info_list.size(); 671 UpdateDisplays(new_display_info_list); 672} 673 674void DisplayManager::ScaleDisplayImpl() { 675 DCHECK(!displays_.empty()); 676 std::vector<DisplayInfo> new_display_info_list; 677 for (DisplayList::const_iterator iter = displays_.begin(); 678 iter != displays_.end(); ++iter) { 679 DisplayInfo display_info = GetDisplayInfo(iter->id()); 680 display_info.set_device_scale_factor( 681 display_info.device_scale_factor() == 1.0f ? 2.0f : 1.0f); 682 new_display_info_list.push_back(display_info); 683 } 684 UpdateDisplays(new_display_info_list); 685} 686 687gfx::Display& DisplayManager::FindDisplayForRootWindow( 688 const aura::RootWindow* root_window) { 689 int64 id = root_window->GetProperty(kDisplayIdKey); 690 // if id is |kInvaildDisplayID|, it's being deleted. 691 DCHECK(id != gfx::Display::kInvalidDisplayID); 692 gfx::Display& display = FindDisplayForId(id); 693 DCHECK(display.is_valid()); 694 return display; 695} 696 697gfx::Display& DisplayManager::FindDisplayForId(int64 id) { 698 for (DisplayList::iterator iter = displays_.begin(); 699 iter != displays_.end(); ++iter) { 700 if ((*iter).id() == id) 701 return *iter; 702 } 703 DLOG(WARNING) << "Could not find display:" << id; 704 return GetInvalidDisplay(); 705} 706 707void DisplayManager::AddDisplayFromSpec(const std::string& spec) { 708 DisplayInfo display_info = DisplayInfo::CreateFromSpec(spec); 709 InsertAndUpdateDisplayInfo(display_info); 710 gfx::Display display = CreateDisplayFromDisplayInfoById(display_info.id()); 711 displays_.push_back(display); 712} 713 714void DisplayManager::InsertAndUpdateDisplayInfo(const DisplayInfo& new_info) { 715 std::map<int64, DisplayInfo>::iterator info = 716 display_info_.find(new_info.id()); 717 if (info != display_info_.end()) 718 info->second.Copy(new_info); 719 else { 720 display_info_[new_info.id()] = new_info; 721 display_info_[new_info.id()].set_native(false); 722 } 723 display_info_[new_info.id()].UpdateDisplaySize(); 724} 725 726gfx::Display DisplayManager::CreateDisplayFromDisplayInfoById(int64 id) { 727 DCHECK(display_info_.find(id) != display_info_.end()); 728 const DisplayInfo& display_info = display_info_[id]; 729 730 gfx::Display new_display(display_info.id()); 731 gfx::Rect bounds_in_pixel(display_info.size_in_pixel()); 732 733 // Simply set the origin to (0,0). The primary display's origin is 734 // always (0,0) and the secondary display's bounds will be updated 735 // by |DisplayController::UpdateDisplayBoundsForLayout|. 736 new_display.SetScaleAndBounds( 737 display_info.device_scale_factor(), gfx::Rect(bounds_in_pixel.size())); 738 new_display.set_rotation(display_info.rotation()); 739 return new_display; 740} 741 742} // namespace internal 743} // namespace ash 744