| OLD | NEW |
| 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 <set> | 7 #include <set> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 new_display_info_list.end(), | 351 new_display_info_list.end(), |
| 352 DisplayInfoSortFunctor()); | 352 DisplayInfoSortFunctor()); |
| 353 DisplayList removed_displays; | 353 DisplayList removed_displays; |
| 354 std::vector<size_t> changed_display_indices; | 354 std::vector<size_t> changed_display_indices; |
| 355 std::vector<size_t> added_display_indices; | 355 std::vector<size_t> added_display_indices; |
| 356 | 356 |
| 357 DisplayList::iterator curr_iter = displays_.begin(); | 357 DisplayList::iterator curr_iter = displays_.begin(); |
| 358 DisplayInfoList::const_iterator new_info_iter = new_display_info_list.begin(); | 358 DisplayInfoList::const_iterator new_info_iter = new_display_info_list.begin(); |
| 359 | 359 |
| 360 DisplayList new_displays; | 360 DisplayList new_displays; |
| 361 bool update_mouse_location = false; |
| 362 |
| 361 while (curr_iter != displays_.end() || | 363 while (curr_iter != displays_.end() || |
| 362 new_info_iter != new_display_info_list.end()) { | 364 new_info_iter != new_display_info_list.end()) { |
| 363 if (curr_iter == displays_.end()) { | 365 if (curr_iter == displays_.end()) { |
| 364 // more displays in new list. | 366 // more displays in new list. |
| 365 added_display_indices.push_back(new_displays.size()); | 367 added_display_indices.push_back(new_displays.size()); |
| 366 InsertAndUpdateDisplayInfo(*new_info_iter); | 368 InsertAndUpdateDisplayInfo(*new_info_iter); |
| 367 new_displays.push_back( | 369 new_displays.push_back( |
| 368 CreateDisplayFromDisplayInfoById(new_info_iter->id())); | 370 CreateDisplayFromDisplayInfoById(new_info_iter->id())); |
| 369 ++new_info_iter; | 371 ++new_info_iter; |
| 370 } else if (new_info_iter == new_display_info_list.end()) { | 372 } else if (new_info_iter == new_display_info_list.end()) { |
| 371 // more displays in current list. | 373 // more displays in current list. |
| 372 removed_displays.push_back(*curr_iter); | 374 removed_displays.push_back(*curr_iter); |
| 373 ++curr_iter; | 375 ++curr_iter; |
| 376 update_mouse_location = true; |
| 374 } else if (curr_iter->id() == new_info_iter->id()) { | 377 } else if (curr_iter->id() == new_info_iter->id()) { |
| 375 const gfx::Display& current_display = *curr_iter; | 378 const gfx::Display& current_display = *curr_iter; |
| 376 // Copy the info because |CreateDisplayFromInfo| updates the instance. | 379 // Copy the info because |CreateDisplayFromInfo| updates the instance. |
| 377 const DisplayInfo current_display_info = | 380 const DisplayInfo current_display_info = |
| 378 GetDisplayInfo(current_display.id()); | 381 GetDisplayInfo(current_display.id()); |
| 379 InsertAndUpdateDisplayInfo(*new_info_iter); | 382 InsertAndUpdateDisplayInfo(*new_info_iter); |
| 380 gfx::Display new_display = | 383 gfx::Display new_display = |
| 381 CreateDisplayFromDisplayInfoById(new_info_iter->id()); | 384 CreateDisplayFromDisplayInfoById(new_info_iter->id()); |
| 382 const DisplayInfo& new_display_info = GetDisplayInfo(new_display.id()); | 385 const DisplayInfo& new_display_info = GetDisplayInfo(new_display.id()); |
| 386 |
| 387 bool host_window_bounds_changed = |
| 388 current_display_info.bounds_in_pixel() != |
| 389 new_display_info.bounds_in_pixel(); |
| 390 |
| 383 // TODO(oshima): Rotating square dislay doesn't work as the size | 391 // TODO(oshima): Rotating square dislay doesn't work as the size |
| 384 // won't change. This doesn't cause a problem now as there is no | 392 // won't change. This doesn't cause a problem now as there is no |
| 385 // such display. This will be fixed by comparing the rotation as | 393 // such display. This will be fixed by comparing the rotation as |
| 386 // well when the rotation variable is added to gfx::Display. | 394 // well when the rotation variable is added to gfx::Display. |
| 387 if (force_bounds_changed_ || | 395 if (force_bounds_changed_ || |
| 388 (current_display_info.bounds_in_pixel() != | 396 host_window_bounds_changed || |
| 389 new_display_info.bounds_in_pixel()) || | |
| 390 (current_display.device_scale_factor() != | 397 (current_display.device_scale_factor() != |
| 391 new_display.device_scale_factor()) || | 398 new_display.device_scale_factor()) || |
| 392 (current_display_info.size_in_pixel() != | 399 (current_display_info.size_in_pixel() != |
| 393 new_display.GetSizeInPixel())) { | 400 new_display.GetSizeInPixel())) { |
| 401 |
| 402 // Don't update mouse location if the display size has |
| 403 // changed due to rotation or zooming. |
| 404 if (host_window_bounds_changed) |
| 405 update_mouse_location = true; |
| 406 |
| 394 changed_display_indices.push_back(new_displays.size()); | 407 changed_display_indices.push_back(new_displays.size()); |
| 395 } | 408 } |
| 396 | 409 |
| 397 new_display.UpdateWorkAreaFromInsets(current_display.GetWorkAreaInsets()); | 410 new_display.UpdateWorkAreaFromInsets(current_display.GetWorkAreaInsets()); |
| 398 new_displays.push_back(new_display); | 411 new_displays.push_back(new_display); |
| 399 ++curr_iter; | 412 ++curr_iter; |
| 400 ++new_info_iter; | 413 ++new_info_iter; |
| 401 } else if (curr_iter->id() < new_info_iter->id()) { | 414 } else if (curr_iter->id() < new_info_iter->id()) { |
| 402 // more displays in current list between ids, which means it is deleted. | 415 // more displays in current list between ids, which means it is deleted. |
| 403 removed_displays.push_back(*curr_iter); | 416 removed_displays.push_back(*curr_iter); |
| 404 ++curr_iter; | 417 ++curr_iter; |
| 418 update_mouse_location = true; |
| 405 } else { | 419 } else { |
| 406 // more displays in new list between ids, which means it is added. | 420 // more displays in new list between ids, which means it is added. |
| 407 added_display_indices.push_back(new_displays.size()); | 421 added_display_indices.push_back(new_displays.size()); |
| 408 InsertAndUpdateDisplayInfo(*new_info_iter); | 422 InsertAndUpdateDisplayInfo(*new_info_iter); |
| 409 new_displays.push_back( | 423 new_displays.push_back( |
| 410 CreateDisplayFromDisplayInfoById(new_info_iter->id())); | 424 CreateDisplayFromDisplayInfoById(new_info_iter->id())); |
| 411 ++new_info_iter; | 425 ++new_info_iter; |
| 412 } | 426 } |
| 413 } | 427 } |
| 414 | 428 |
| 415 // Do not update |displays_| if there's nothing to be updated. Without this, | 429 // Do not update |displays_| if there's nothing to be updated. Without this, |
| 416 // it will not update the display layout, which causes the bug | 430 // it will not update the display layout, which causes the bug |
| 417 // http://crbug.com/155948. | 431 // http://crbug.com/155948. |
| 418 if (changed_display_indices.empty() && added_display_indices.empty() && | 432 if (changed_display_indices.empty() && added_display_indices.empty() && |
| 419 removed_displays.empty()) { | 433 removed_displays.empty()) { |
| 420 return; | 434 return; |
| 421 } | 435 } |
| 422 | 436 |
| 437 DisplayController* display_controller = |
| 438 Shell::GetInstance()->display_controller(); |
| 439 gfx::Point mouse_location_in_native; |
| 440 display_controller->NotifyDisplayConfigurationChanging(); |
| 441 mouse_location_in_native = display_controller->GetNativeMouseCursorLocation(); |
| 442 |
| 423 displays_ = new_displays; | 443 displays_ = new_displays; |
| 424 | 444 |
| 425 base::AutoReset<bool> resetter(&change_display_upon_host_resize_, false); | 445 base::AutoReset<bool> resetter(&change_display_upon_host_resize_, false); |
| 426 | 446 |
| 427 // Temporarily add displays to be removed because display object | 447 // Temporarily add displays to be removed because display object |
| 428 // being removed are accessed during shutting down the root. | 448 // being removed are accessed during shutting down the root. |
| 429 displays_.insert(displays_.end(), removed_displays.begin(), | 449 displays_.insert(displays_.end(), removed_displays.begin(), |
| 430 removed_displays.end()); | 450 removed_displays.end()); |
| 431 DisplayController* display_controller = | |
| 432 Shell::GetInstance()->display_controller(); | |
| 433 // |display_controller| is NULL during the bootstrap. | |
| 434 if (display_controller) | |
| 435 display_controller->NotifyDisplayConfigurationChanging(); | |
| 436 | 451 |
| 437 for (DisplayList::const_reverse_iterator iter = removed_displays.rbegin(); | 452 for (DisplayList::const_reverse_iterator iter = removed_displays.rbegin(); |
| 438 iter != removed_displays.rend(); ++iter) { | 453 iter != removed_displays.rend(); ++iter) { |
| 439 Shell::GetInstance()->screen()->NotifyDisplayRemoved(displays_.back()); | 454 Shell::GetInstance()->screen()->NotifyDisplayRemoved(displays_.back()); |
| 440 displays_.pop_back(); | 455 displays_.pop_back(); |
| 441 } | 456 } |
| 442 for (std::vector<size_t>::iterator iter = added_display_indices.begin(); | 457 for (std::vector<size_t>::iterator iter = added_display_indices.begin(); |
| 443 iter != added_display_indices.end(); ++iter) { | 458 iter != added_display_indices.end(); ++iter) { |
| 444 Shell::GetInstance()->screen()->NotifyDisplayAdded(displays_[*iter]); | 459 Shell::GetInstance()->screen()->NotifyDisplayAdded(displays_[*iter]); |
| 445 } | 460 } |
| 446 for (std::vector<size_t>::iterator iter = changed_display_indices.begin(); | 461 for (std::vector<size_t>::iterator iter = changed_display_indices.begin(); |
| 447 iter != changed_display_indices.end(); ++iter) { | 462 iter != changed_display_indices.end(); ++iter) { |
| 448 Shell::GetInstance()->screen()->NotifyBoundsChanged(displays_[*iter]); | 463 Shell::GetInstance()->screen()->NotifyBoundsChanged(displays_[*iter]); |
| 449 } | 464 } |
| 450 if (display_controller) | 465 display_controller->NotifyDisplayConfigurationChanged(); |
| 451 display_controller->NotifyDisplayConfigurationChanged(); | 466 if (update_mouse_location) |
| 467 display_controller->EnsurePointerInDisplays(); |
| 468 else |
| 469 display_controller->UpdateMouseCursor(mouse_location_in_native); |
| 452 | 470 |
| 453 EnsurePointerInDisplays(); | |
| 454 #if defined(USE_X11) && defined(OS_CHROMEOS) | 471 #if defined(USE_X11) && defined(OS_CHROMEOS) |
| 455 if (!changed_display_indices.empty() && base::chromeos::IsRunningOnChromeOS()) | 472 if (!changed_display_indices.empty() && base::chromeos::IsRunningOnChromeOS()) |
| 456 ui::ClearX11DefaultRootWindow(); | 473 ui::ClearX11DefaultRootWindow(); |
| 457 #endif | 474 #endif |
| 458 } | 475 } |
| 459 | 476 |
| 460 gfx::Display* DisplayManager::GetDisplayAt(size_t index) { | 477 gfx::Display* DisplayManager::GetDisplayAt(size_t index) { |
| 461 return index < displays_.size() ? &displays_[index] : NULL; | 478 return index < displays_.size() ? &displays_[index] : NULL; |
| 462 } | 479 } |
| 463 | 480 |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 648 return GetInvalidDisplay(); | 665 return GetInvalidDisplay(); |
| 649 } | 666 } |
| 650 | 667 |
| 651 void DisplayManager::AddDisplayFromSpec(const std::string& spec) { | 668 void DisplayManager::AddDisplayFromSpec(const std::string& spec) { |
| 652 DisplayInfo display_info = DisplayInfo::CreateFromSpec(spec); | 669 DisplayInfo display_info = DisplayInfo::CreateFromSpec(spec); |
| 653 InsertAndUpdateDisplayInfo(display_info); | 670 InsertAndUpdateDisplayInfo(display_info); |
| 654 gfx::Display display = CreateDisplayFromDisplayInfoById(display_info.id()); | 671 gfx::Display display = CreateDisplayFromDisplayInfoById(display_info.id()); |
| 655 displays_.push_back(display); | 672 displays_.push_back(display); |
| 656 } | 673 } |
| 657 | 674 |
| 658 void DisplayManager::EnsurePointerInDisplays() { | |
| 659 // Don't try to move the pointer during the boot/startup. | |
| 660 if (!DisplayController::HasPrimaryDisplay()) | |
| 661 return; | |
| 662 gfx::Point location_in_screen = Shell::GetScreen()->GetCursorScreenPoint(); | |
| 663 gfx::Point target_location; | |
| 664 int64 closest_distance_squared = -1; | |
| 665 | |
| 666 for (DisplayList::const_iterator iter = displays_.begin(); | |
| 667 iter != displays_.end(); ++iter) { | |
| 668 const gfx::Rect& display_bounds = iter->bounds(); | |
| 669 | |
| 670 if (display_bounds.Contains(location_in_screen)) { | |
| 671 target_location = location_in_screen; | |
| 672 break; | |
| 673 } | |
| 674 gfx::Point center = display_bounds.CenterPoint(); | |
| 675 // Use the distance squared from the center of the dislay. This is not | |
| 676 // exactly "closest" display, but good enough to pick one | |
| 677 // appropriate (and there are at most two displays). | |
| 678 // We don't care about actual distance, only relative to other displays, so | |
| 679 // using the LengthSquared() is cheaper than Length(). | |
| 680 int64 distance_squared = (center - location_in_screen).LengthSquared(); | |
| 681 if (closest_distance_squared < 0 || | |
| 682 closest_distance_squared > distance_squared) { | |
| 683 target_location = center; | |
| 684 closest_distance_squared = distance_squared; | |
| 685 } | |
| 686 } | |
| 687 | |
| 688 aura::RootWindow* root_window = Shell::GetPrimaryRootWindow(); | |
| 689 aura::client::ScreenPositionClient* client = | |
| 690 aura::client::GetScreenPositionClient(root_window); | |
| 691 client->ConvertPointFromScreen(root_window, &target_location); | |
| 692 | |
| 693 root_window->MoveCursorTo(target_location); | |
| 694 } | |
| 695 | |
| 696 void DisplayManager::InsertAndUpdateDisplayInfo(const DisplayInfo& new_info) { | 675 void DisplayManager::InsertAndUpdateDisplayInfo(const DisplayInfo& new_info) { |
| 697 std::map<int64, DisplayInfo>::iterator info = | 676 std::map<int64, DisplayInfo>::iterator info = |
| 698 display_info_.find(new_info.id()); | 677 display_info_.find(new_info.id()); |
| 699 if (info != display_info_.end()) | 678 if (info != display_info_.end()) |
| 700 info->second.Copy(new_info); | 679 info->second.Copy(new_info); |
| 701 else { | 680 else { |
| 702 display_info_[new_info.id()] = new_info; | 681 display_info_[new_info.id()] = new_info; |
| 703 display_info_[new_info.id()].set_native(false); | 682 display_info_[new_info.id()].set_native(false); |
| 704 } | 683 } |
| 705 bool on_chromeos = false; | 684 bool on_chromeos = false; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 731 // always (0,0) and the secondary display's bounds will be updated | 710 // always (0,0) and the secondary display's bounds will be updated |
| 732 // by |DisplayController::UpdateDisplayBoundsForLayout|. | 711 // by |DisplayController::UpdateDisplayBoundsForLayout|. |
| 733 new_display.SetScaleAndBounds( | 712 new_display.SetScaleAndBounds( |
| 734 display_info.device_scale_factor(), gfx::Rect(bounds_in_pixel.size())); | 713 display_info.device_scale_factor(), gfx::Rect(bounds_in_pixel.size())); |
| 735 new_display.set_rotation(display_info.rotation()); | 714 new_display.set_rotation(display_info.rotation()); |
| 736 return new_display; | 715 return new_display; |
| 737 } | 716 } |
| 738 | 717 |
| 739 } // namespace internal | 718 } // namespace internal |
| 740 } // namespace ash | 719 } // namespace ash |
| OLD | NEW |