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 |