Chromium Code Reviews| 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 native_mouse_location; | |
|
Jun Mukai
2013/04/06 03:13:39
mouse_location_in_native would be more consistent?
oshima
2013/04/08 18:00:40
Done.
| |
| 440 // |display_controller| is NULL during the bootstrap. | |
| 441 if (display_controller) { | |
| 442 display_controller->NotifyDisplayConfigurationChanging(); | |
| 443 native_mouse_location = display_controller->GetNativeMouseCursorLocation(); | |
| 444 } | |
| 445 | |
| 423 displays_ = new_displays; | 446 displays_ = new_displays; |
| 424 | 447 |
| 425 base::AutoReset<bool> resetter(&change_display_upon_host_resize_, false); | 448 base::AutoReset<bool> resetter(&change_display_upon_host_resize_, false); |
| 426 | 449 |
| 427 // Temporarily add displays to be removed because display object | 450 // Temporarily add displays to be removed because display object |
| 428 // being removed are accessed during shutting down the root. | 451 // being removed are accessed during shutting down the root. |
| 429 displays_.insert(displays_.end(), removed_displays.begin(), | 452 displays_.insert(displays_.end(), removed_displays.begin(), |
| 430 removed_displays.end()); | 453 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 | 454 |
| 437 for (DisplayList::const_reverse_iterator iter = removed_displays.rbegin(); | 455 for (DisplayList::const_reverse_iterator iter = removed_displays.rbegin(); |
| 438 iter != removed_displays.rend(); ++iter) { | 456 iter != removed_displays.rend(); ++iter) { |
| 439 Shell::GetInstance()->screen()->NotifyDisplayRemoved(displays_.back()); | 457 Shell::GetInstance()->screen()->NotifyDisplayRemoved(displays_.back()); |
| 440 displays_.pop_back(); | 458 displays_.pop_back(); |
| 441 } | 459 } |
| 442 for (std::vector<size_t>::iterator iter = added_display_indices.begin(); | 460 for (std::vector<size_t>::iterator iter = added_display_indices.begin(); |
| 443 iter != added_display_indices.end(); ++iter) { | 461 iter != added_display_indices.end(); ++iter) { |
| 444 Shell::GetInstance()->screen()->NotifyDisplayAdded(displays_[*iter]); | 462 Shell::GetInstance()->screen()->NotifyDisplayAdded(displays_[*iter]); |
| 445 } | 463 } |
| 446 for (std::vector<size_t>::iterator iter = changed_display_indices.begin(); | 464 for (std::vector<size_t>::iterator iter = changed_display_indices.begin(); |
| 447 iter != changed_display_indices.end(); ++iter) { | 465 iter != changed_display_indices.end(); ++iter) { |
| 448 Shell::GetInstance()->screen()->NotifyBoundsChanged(displays_[*iter]); | 466 Shell::GetInstance()->screen()->NotifyBoundsChanged(displays_[*iter]); |
| 449 } | 467 } |
| 450 if (display_controller) | 468 if (display_controller) { |
| 451 display_controller->NotifyDisplayConfigurationChanged(); | 469 display_controller->NotifyDisplayConfigurationChanged(); |
| 452 | 470 if (update_mouse_location) |
| 453 EnsurePointerInDisplays(); | 471 display_controller->EnsurePointerInDisplays(); |
| 472 else | |
| 473 display_controller->UpdateMouseCursor(native_mouse_location); | |
|
Jun Mukai
2013/04/06 03:13:39
Why this needs to be called?
oshima
2013/04/08 18:00:40
Yes, we need to update the cursor when rotated.
| |
| 474 } | |
| 454 #if defined(USE_X11) && defined(OS_CHROMEOS) | 475 #if defined(USE_X11) && defined(OS_CHROMEOS) |
| 455 if (!changed_display_indices.empty() && base::chromeos::IsRunningOnChromeOS()) | 476 if (!changed_display_indices.empty() && base::chromeos::IsRunningOnChromeOS()) |
| 456 ui::ClearX11DefaultRootWindow(); | 477 ui::ClearX11DefaultRootWindow(); |
| 457 #endif | 478 #endif |
| 458 } | 479 } |
| 459 | 480 |
| 460 gfx::Display* DisplayManager::GetDisplayAt(size_t index) { | 481 gfx::Display* DisplayManager::GetDisplayAt(size_t index) { |
| 461 return index < displays_.size() ? &displays_[index] : NULL; | 482 return index < displays_.size() ? &displays_[index] : NULL; |
| 462 } | 483 } |
| 463 | 484 |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 648 return GetInvalidDisplay(); | 669 return GetInvalidDisplay(); |
| 649 } | 670 } |
| 650 | 671 |
| 651 void DisplayManager::AddDisplayFromSpec(const std::string& spec) { | 672 void DisplayManager::AddDisplayFromSpec(const std::string& spec) { |
| 652 DisplayInfo display_info = DisplayInfo::CreateFromSpec(spec); | 673 DisplayInfo display_info = DisplayInfo::CreateFromSpec(spec); |
| 653 InsertAndUpdateDisplayInfo(display_info); | 674 InsertAndUpdateDisplayInfo(display_info); |
| 654 gfx::Display display = CreateDisplayFromDisplayInfoById(display_info.id()); | 675 gfx::Display display = CreateDisplayFromDisplayInfoById(display_info.id()); |
| 655 displays_.push_back(display); | 676 displays_.push_back(display); |
| 656 } | 677 } |
| 657 | 678 |
| 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) { | 679 void DisplayManager::InsertAndUpdateDisplayInfo(const DisplayInfo& new_info) { |
| 697 std::map<int64, DisplayInfo>::iterator info = | 680 std::map<int64, DisplayInfo>::iterator info = |
| 698 display_info_.find(new_info.id()); | 681 display_info_.find(new_info.id()); |
| 699 if (info != display_info_.end()) | 682 if (info != display_info_.end()) |
| 700 info->second.Copy(new_info); | 683 info->second.Copy(new_info); |
| 701 else { | 684 else { |
| 702 display_info_[new_info.id()] = new_info; | 685 display_info_[new_info.id()] = new_info; |
| 703 display_info_[new_info.id()].set_native(false); | 686 display_info_[new_info.id()].set_native(false); |
| 704 } | 687 } |
| 705 bool on_chromeos = false; | 688 bool on_chromeos = false; |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 731 // always (0,0) and the secondary display's bounds will be updated | 714 // always (0,0) and the secondary display's bounds will be updated |
| 732 // by |DisplayController::UpdateDisplayBoundsForLayout|. | 715 // by |DisplayController::UpdateDisplayBoundsForLayout|. |
| 733 new_display.SetScaleAndBounds( | 716 new_display.SetScaleAndBounds( |
| 734 display_info.device_scale_factor(), gfx::Rect(bounds_in_pixel.size())); | 717 display_info.device_scale_factor(), gfx::Rect(bounds_in_pixel.size())); |
| 735 new_display.set_rotation(display_info.rotation()); | 718 new_display.set_rotation(display_info.rotation()); |
| 736 return new_display; | 719 return new_display; |
| 737 } | 720 } |
| 738 | 721 |
| 739 } // namespace internal | 722 } // namespace internal |
| 740 } // namespace ash | 723 } // namespace ash |
| OLD | NEW |