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 <cmath> | 7 #include <cmath> |
8 #include <set> | 8 #include <set> |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "ash/ash_switches.h" | 12 #include "ash/ash_switches.h" |
13 #include "ash/display/display_layout_store.h" | 13 #include "ash/display/display_layout_store.h" |
14 #include "ash/display/screen_ash.h" | 14 #include "ash/display/screen_ash.h" |
15 #include "ash/screen_util.h" | 15 #include "ash/screen_util.h" |
16 #include "ash/shell.h" | 16 #include "ash/shell.h" |
17 #include "base/auto_reset.h" | 17 #include "base/auto_reset.h" |
18 #include "base/command_line.h" | 18 #include "base/command_line.h" |
19 #include "base/logging.h" | 19 #include "base/logging.h" |
20 #include "base/metrics/histogram.h" | 20 #include "base/metrics/histogram.h" |
21 #include "base/strings/string_number_conversions.h" | 21 #include "base/strings/string_number_conversions.h" |
22 #include "base/strings/string_split.h" | 22 #include "base/strings/string_split.h" |
23 #include "base/strings/stringprintf.h" | 23 #include "base/strings/stringprintf.h" |
24 #include "base/strings/utf_string_conversions.h" | 24 #include "base/strings/utf_string_conversions.h" |
25 #include "grit/ash_strings.h" | 25 #include "grit/ash_strings.h" |
26 #include "ui/base/l10n/l10n_util.h" | 26 #include "ui/base/l10n/l10n_util.h" |
27 #include "ui/base/layout.h" | 27 #include "ui/base/layout.h" |
28 #include "ui/base/resource/resource_bundle.h" | 28 #include "ui/base/resource/resource_bundle.h" |
29 #include "ui/gfx/display.h" | 29 #include "ui/gfx/display.h" |
30 #include "ui/gfx/display_observer.h" | |
31 #include "ui/gfx/rect.h" | 30 #include "ui/gfx/rect.h" |
32 #include "ui/gfx/screen.h" | 31 #include "ui/gfx/screen.h" |
33 #include "ui/gfx/size_conversions.h" | 32 #include "ui/gfx/size_conversions.h" |
34 | 33 |
35 #if defined(USE_X11) | 34 #if defined(USE_X11) |
36 #include "ui/base/x/x11_util.h" | 35 #include "ui/base/x/x11_util.h" |
37 #endif | 36 #endif |
38 | 37 |
39 #if defined(OS_CHROMEOS) | 38 #if defined(OS_CHROMEOS) |
40 #include "ash/display/display_configurator_animation.h" | 39 #include "ash/display/display_configurator_animation.h" |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
341 delegate_->PreDisplayConfigurationChange(false); | 340 delegate_->PreDisplayConfigurationChange(false); |
342 // PreDisplayConfigurationChange(false); | 341 // PreDisplayConfigurationChange(false); |
343 // TODO(oshima): Call UpdateDisplays instead. | 342 // TODO(oshima): Call UpdateDisplays instead. |
344 const DisplayLayout layout = GetCurrentDisplayLayout(); | 343 const DisplayLayout layout = GetCurrentDisplayLayout(); |
345 UpdateDisplayBoundsForLayoutById( | 344 UpdateDisplayBoundsForLayoutById( |
346 layout, primary, | 345 layout, primary, |
347 ScreenUtil::GetSecondaryDisplay().id()); | 346 ScreenUtil::GetSecondaryDisplay().id()); |
348 | 347 |
349 // Primary's bounds stay the same. Just notify bounds change | 348 // Primary's bounds stay the same. Just notify bounds change |
350 // on the secondary. | 349 // on the secondary. |
351 screen_ash_->NotifyMetricsChanged( | 350 screen_ash_->NotifyBoundsChanged( |
352 ScreenUtil::GetSecondaryDisplay(), | 351 ScreenUtil::GetSecondaryDisplay()); |
353 gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS | | |
354 gfx::DisplayObserver::DISPLAY_METRIC_WORK_AREA); | |
355 if (delegate_) | 352 if (delegate_) |
356 delegate_->PostDisplayConfigurationChange(); | 353 delegate_->PostDisplayConfigurationChange(); |
357 } | 354 } |
358 } | 355 } |
359 | 356 |
360 const gfx::Display& DisplayManager::GetDisplayForId(int64 id) const { | 357 const gfx::Display& DisplayManager::GetDisplayForId(int64 id) const { |
361 gfx::Display* display = | 358 gfx::Display* display = |
362 const_cast<DisplayManager*>(this)->FindDisplayForId(id); | 359 const_cast<DisplayManager*>(this)->FindDisplayForId(id); |
363 return display ? *display : GetInvalidDisplay(); | 360 return display ? *display : GetInvalidDisplay(); |
364 } | 361 } |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 ": Multiple display test does not work on Windows bots. Please " | 636 ": Multiple display test does not work on Windows bots. Please " |
640 "skip (don't disable) the test using SupportsMultipleDisplays()"; | 637 "skip (don't disable) the test using SupportsMultipleDisplays()"; |
641 #endif | 638 #endif |
642 | 639 |
643 DisplayInfoList new_display_info_list = updated_display_info_list; | 640 DisplayInfoList new_display_info_list = updated_display_info_list; |
644 std::sort(displays_.begin(), displays_.end(), DisplaySortFunctor()); | 641 std::sort(displays_.begin(), displays_.end(), DisplaySortFunctor()); |
645 std::sort(new_display_info_list.begin(), | 642 std::sort(new_display_info_list.begin(), |
646 new_display_info_list.end(), | 643 new_display_info_list.end(), |
647 DisplayInfoSortFunctor()); | 644 DisplayInfoSortFunctor()); |
648 DisplayList removed_displays; | 645 DisplayList removed_displays; |
649 std::map<size_t, uint32_t> display_changes; | 646 std::vector<size_t> changed_display_indices; |
650 std::vector<size_t> added_display_indices; | 647 std::vector<size_t> added_display_indices; |
651 | 648 |
652 DisplayList::iterator curr_iter = displays_.begin(); | 649 DisplayList::iterator curr_iter = displays_.begin(); |
653 DisplayInfoList::const_iterator new_info_iter = new_display_info_list.begin(); | 650 DisplayInfoList::const_iterator new_info_iter = new_display_info_list.begin(); |
654 | 651 |
655 DisplayList new_displays; | 652 DisplayList new_displays; |
656 | 653 |
657 // Use the internal display or 1st as the mirror source, then scale | 654 // Use the internal display or 1st as the mirror source, then scale |
658 // the root window so that it matches the external display's | 655 // the root window so that it matches the external display's |
659 // resolution. This is necessary in order for scaling to work while | 656 // resolution. This is necessary in order for scaling to work while |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
709 } else if (curr_iter->id() == new_info_iter->id()) { | 706 } else if (curr_iter->id() == new_info_iter->id()) { |
710 const gfx::Display& current_display = *curr_iter; | 707 const gfx::Display& current_display = *curr_iter; |
711 // Copy the info because |CreateDisplayFromInfo| updates the instance. | 708 // Copy the info because |CreateDisplayFromInfo| updates the instance. |
712 const DisplayInfo current_display_info = | 709 const DisplayInfo current_display_info = |
713 GetDisplayInfo(current_display.id()); | 710 GetDisplayInfo(current_display.id()); |
714 InsertAndUpdateDisplayInfo(*new_info_iter); | 711 InsertAndUpdateDisplayInfo(*new_info_iter); |
715 gfx::Display new_display = | 712 gfx::Display new_display = |
716 CreateDisplayFromDisplayInfoById(new_info_iter->id()); | 713 CreateDisplayFromDisplayInfoById(new_info_iter->id()); |
717 const DisplayInfo& new_display_info = GetDisplayInfo(new_display.id()); | 714 const DisplayInfo& new_display_info = GetDisplayInfo(new_display.id()); |
718 | 715 |
719 uint32_t metrics = gfx::DisplayObserver::DISPLAY_METRIC_NONE; | 716 bool host_window_bounds_changed = |
| 717 current_display_info.bounds_in_native() != |
| 718 new_display_info.bounds_in_native(); |
720 | 719 |
721 // At that point the new Display objects we have are not entirely updated, | 720 if (force_bounds_changed_ || |
722 // they are missing the translation related to the Display disposition in | 721 host_window_bounds_changed || |
723 // the layout. | 722 (current_display.device_scale_factor() != |
724 // Using display.bounds() and display.work_area() would fail most of the | 723 new_display.device_scale_factor()) || |
725 // time. | |
726 if (force_bounds_changed_ || (current_display_info.bounds_in_native() != | |
727 new_display_info.bounds_in_native()) || | |
728 (current_display_info.size_in_pixel() != | 724 (current_display_info.size_in_pixel() != |
729 new_display.GetSizeInPixel())) { | 725 new_display.GetSizeInPixel()) || |
730 metrics |= gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS | | 726 (current_display.rotation() != new_display.rotation())) { |
731 gfx::DisplayObserver::DISPLAY_METRIC_WORK_AREA; | 727 changed_display_indices.push_back(new_displays.size()); |
732 } | |
733 | |
734 if (current_display.device_scale_factor() != | |
735 new_display.device_scale_factor()) { | |
736 metrics |= gfx::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR; | |
737 } | |
738 | |
739 if (current_display.rotation() != new_display.rotation()) | |
740 metrics |= gfx::DisplayObserver::DISPLAY_METRIC_ROTATION; | |
741 | |
742 if (metrics != gfx::DisplayObserver::DISPLAY_METRIC_NONE) { | |
743 display_changes.insert( | |
744 std::pair<size_t, uint32_t>(new_displays.size(), metrics)); | |
745 } | 728 } |
746 | 729 |
747 new_display.UpdateWorkAreaFromInsets(current_display.GetWorkAreaInsets()); | 730 new_display.UpdateWorkAreaFromInsets(current_display.GetWorkAreaInsets()); |
748 new_displays.push_back(new_display); | 731 new_displays.push_back(new_display); |
749 ++curr_iter; | 732 ++curr_iter; |
750 ++new_info_iter; | 733 ++new_info_iter; |
751 } else if (curr_iter->id() < new_info_iter->id()) { | 734 } else if (curr_iter->id() < new_info_iter->id()) { |
752 // more displays in current list between ids, which means it is deleted. | 735 // more displays in current list between ids, which means it is deleted. |
753 removed_displays.push_back(*curr_iter); | 736 removed_displays.push_back(*curr_iter); |
754 ++curr_iter; | 737 ++curr_iter; |
755 } else { | 738 } else { |
756 // more displays in new list between ids, which means it is added. | 739 // more displays in new list between ids, which means it is added. |
757 added_display_indices.push_back(new_displays.size()); | 740 added_display_indices.push_back(new_displays.size()); |
758 InsertAndUpdateDisplayInfo(*new_info_iter); | 741 InsertAndUpdateDisplayInfo(*new_info_iter); |
759 new_displays.push_back( | 742 new_displays.push_back( |
760 CreateDisplayFromDisplayInfoById(new_info_iter->id())); | 743 CreateDisplayFromDisplayInfoById(new_info_iter->id())); |
761 ++new_info_iter; | 744 ++new_info_iter; |
762 } | 745 } |
763 } | 746 } |
764 | 747 |
765 scoped_ptr<NonDesktopDisplayUpdater> non_desktop_display_updater( | 748 scoped_ptr<NonDesktopDisplayUpdater> non_desktop_display_updater( |
766 new NonDesktopDisplayUpdater(this, delegate_)); | 749 new NonDesktopDisplayUpdater(this, delegate_)); |
767 | 750 |
768 // Do not update |displays_| if there's nothing to be updated. Without this, | 751 // Do not update |displays_| if there's nothing to be updated. Without this, |
769 // it will not update the display layout, which causes the bug | 752 // it will not update the display layout, which causes the bug |
770 // http://crbug.com/155948. | 753 // http://crbug.com/155948. |
771 if (display_changes.empty() && added_display_indices.empty() && | 754 if (changed_display_indices.empty() && added_display_indices.empty() && |
772 removed_displays.empty()) { | 755 removed_displays.empty()) { |
773 return; | 756 return; |
774 } | 757 } |
775 // Clear focus if the display has been removed, but don't clear focus if | 758 // Clear focus if the display has been removed, but don't clear focus if |
776 // the destkop has been moved from one display to another | 759 // the destkop has been moved from one display to another |
777 // (mirror -> docked, docked -> single internal). | 760 // (mirror -> docked, docked -> single internal). |
778 bool clear_focus = | 761 bool clear_focus = |
779 !removed_displays.empty() && | 762 !removed_displays.empty() && |
780 !(removed_displays.size() == 1 && added_display_indices.size() == 1); | 763 !(removed_displays.size() == 1 && added_display_indices.size() == 1); |
781 if (delegate_) | 764 if (delegate_) |
782 delegate_->PreDisplayConfigurationChange(clear_focus); | 765 delegate_->PreDisplayConfigurationChange(clear_focus); |
783 | 766 |
784 size_t updated_index; | 767 size_t updated_index; |
785 if (UpdateSecondaryDisplayBoundsForLayout(&new_displays, &updated_index) && | 768 if (UpdateSecondaryDisplayBoundsForLayout(&new_displays, &updated_index) && |
786 std::find(added_display_indices.begin(), | 769 std::find(added_display_indices.begin(), |
787 added_display_indices.end(), | 770 added_display_indices.end(), |
788 updated_index) == added_display_indices.end()) { | 771 updated_index) == added_display_indices.end() && |
789 uint32_t metrics = gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS | | 772 std::find(changed_display_indices.begin(), |
790 gfx::DisplayObserver::DISPLAY_METRIC_WORK_AREA; | 773 changed_display_indices.end(), |
791 if (display_changes.find(updated_index) != display_changes.end()) | 774 updated_index) == changed_display_indices.end()) { |
792 metrics |= display_changes[updated_index]; | 775 changed_display_indices.push_back(updated_index); |
793 | |
794 display_changes[updated_index] = metrics; | |
795 } | 776 } |
796 | 777 |
797 displays_ = new_displays; | 778 displays_ = new_displays; |
798 | 779 |
799 base::AutoReset<bool> resetter(&change_display_upon_host_resize_, false); | 780 base::AutoReset<bool> resetter(&change_display_upon_host_resize_, false); |
800 | 781 |
801 // Temporarily add displays to be removed because display object | 782 // Temporarily add displays to be removed because display object |
802 // being removed are accessed during shutting down the root. | 783 // being removed are accessed during shutting down the root. |
803 displays_.insert(displays_.end(), removed_displays.begin(), | 784 displays_.insert(displays_.end(), removed_displays.begin(), |
804 removed_displays.end()); | 785 removed_displays.end()); |
805 | 786 |
806 for (DisplayList::const_reverse_iterator iter = removed_displays.rbegin(); | 787 for (DisplayList::const_reverse_iterator iter = removed_displays.rbegin(); |
807 iter != removed_displays.rend(); ++iter) { | 788 iter != removed_displays.rend(); ++iter) { |
808 screen_ash_->NotifyDisplayRemoved(displays_.back()); | 789 screen_ash_->NotifyDisplayRemoved(displays_.back()); |
809 displays_.pop_back(); | 790 displays_.pop_back(); |
810 } | 791 } |
811 // Close the non desktop window here to avoid creating two compositor on | 792 // Close the non desktop window here to avoid creating two compositor on |
812 // one display. | 793 // one display. |
813 if (!non_desktop_display_updater->enabled()) | 794 if (!non_desktop_display_updater->enabled()) |
814 non_desktop_display_updater.reset(); | 795 non_desktop_display_updater.reset(); |
815 for (std::vector<size_t>::iterator iter = added_display_indices.begin(); | 796 for (std::vector<size_t>::iterator iter = added_display_indices.begin(); |
816 iter != added_display_indices.end(); ++iter) { | 797 iter != added_display_indices.end(); ++iter) { |
817 screen_ash_->NotifyDisplayAdded(displays_[*iter]); | 798 screen_ash_->NotifyDisplayAdded(displays_[*iter]); |
818 } | 799 } |
819 // Create the non destkop window after all displays are added so that | 800 // Create the non destkop window after all displays are added so that |
820 // it can mirror the display newly added. This can happen when switching | 801 // it can mirror the display newly added. This can happen when switching |
821 // from dock mode to software mirror mode. | 802 // from dock mode to software mirror mode. |
822 non_desktop_display_updater.reset(); | 803 non_desktop_display_updater.reset(); |
823 for (std::map<size_t, uint32_t>::iterator iter = display_changes.begin(); | 804 for (std::vector<size_t>::iterator iter = changed_display_indices.begin(); |
824 iter != display_changes.end(); | 805 iter != changed_display_indices.end(); ++iter) { |
825 ++iter) { | 806 screen_ash_->NotifyBoundsChanged(displays_[*iter]); |
826 screen_ash_->NotifyMetricsChanged(displays_[iter->first], iter->second); | |
827 } | 807 } |
828 if (delegate_) | 808 if (delegate_) |
829 delegate_->PostDisplayConfigurationChange(); | 809 delegate_->PostDisplayConfigurationChange(); |
830 | 810 |
831 #if defined(USE_X11) && defined(OS_CHROMEOS) | 811 #if defined(USE_X11) && defined(OS_CHROMEOS) |
832 if (!display_changes.empty() && base::SysInfo::IsRunningOnChromeOS()) | 812 if (!changed_display_indices.empty() && base::SysInfo::IsRunningOnChromeOS()) |
833 ui::ClearX11DefaultRootWindow(); | 813 ui::ClearX11DefaultRootWindow(); |
834 #endif | 814 #endif |
835 } | 815 } |
836 | 816 |
837 const gfx::Display& DisplayManager::GetDisplayAt(size_t index) const { | 817 const gfx::Display& DisplayManager::GetDisplayAt(size_t index) const { |
838 DCHECK_LT(index, displays_.size()); | 818 DCHECK_LT(index, displays_.size()); |
839 return displays_[index]; | 819 return displays_[index]; |
840 } | 820 } |
841 | 821 |
842 const gfx::Display& DisplayManager::GetPrimaryDisplayCandidate() const { | 822 const gfx::Display& DisplayManager::GetPrimaryDisplayCandidate() const { |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
970 | 950 |
971 bool DisplayManager::UpdateDisplayBounds(int64 display_id, | 951 bool DisplayManager::UpdateDisplayBounds(int64 display_id, |
972 const gfx::Rect& new_bounds) { | 952 const gfx::Rect& new_bounds) { |
973 if (change_display_upon_host_resize_) { | 953 if (change_display_upon_host_resize_) { |
974 display_info_[display_id].SetBounds(new_bounds); | 954 display_info_[display_id].SetBounds(new_bounds); |
975 // Don't notify observers if the mirrored window has changed. | 955 // Don't notify observers if the mirrored window has changed. |
976 if (software_mirroring_enabled() && mirrored_display_id_ == display_id) | 956 if (software_mirroring_enabled() && mirrored_display_id_ == display_id) |
977 return false; | 957 return false; |
978 gfx::Display* display = FindDisplayForId(display_id); | 958 gfx::Display* display = FindDisplayForId(display_id); |
979 display->SetSize(display_info_[display_id].size_in_pixel()); | 959 display->SetSize(display_info_[display_id].size_in_pixel()); |
980 screen_ash_->NotifyMetricsChanged( | 960 screen_ash_->NotifyBoundsChanged(*display); |
981 *display, gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS); | |
982 return true; | 961 return true; |
983 } | 962 } |
984 return false; | 963 return false; |
985 } | 964 } |
986 | 965 |
987 void DisplayManager::CreateMirrorWindowIfAny() { | 966 void DisplayManager::CreateMirrorWindowIfAny() { |
988 NonDesktopDisplayUpdater updater(this, delegate_); | 967 NonDesktopDisplayUpdater updater(this, delegate_); |
989 } | 968 } |
990 | 969 |
991 void DisplayManager::CreateScreenForShutdown() const { | 970 void DisplayManager::CreateScreenForShutdown() const { |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1140 new_secondary_origin.Offset(-secondary_bounds.width(), offset); | 1119 new_secondary_origin.Offset(-secondary_bounds.width(), offset); |
1141 break; | 1120 break; |
1142 } | 1121 } |
1143 gfx::Insets insets = secondary_display->GetWorkAreaInsets(); | 1122 gfx::Insets insets = secondary_display->GetWorkAreaInsets(); |
1144 secondary_display->set_bounds( | 1123 secondary_display->set_bounds( |
1145 gfx::Rect(new_secondary_origin, secondary_bounds.size())); | 1124 gfx::Rect(new_secondary_origin, secondary_bounds.size())); |
1146 secondary_display->UpdateWorkAreaFromInsets(insets); | 1125 secondary_display->UpdateWorkAreaFromInsets(insets); |
1147 } | 1126 } |
1148 | 1127 |
1149 } // namespace ash | 1128 } // namespace ash |
OLD | NEW |