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