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