OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "ui/display/chromeos/display_configurator.h" | 5 #include "ui/display/chromeos/display_configurator.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/sys_info.h" | 10 #include "base/sys_info.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 // The delay to perform configuration after RRNotify. See the comment for | 25 // The delay to perform configuration after RRNotify. See the comment for |
26 // |configure_timer_|. | 26 // |configure_timer_|. |
27 const int kConfigureDelayMs = 500; | 27 const int kConfigureDelayMs = 500; |
28 | 28 |
29 // The delay spent before reading the display configuration after coming out of | 29 // The delay spent before reading the display configuration after coming out of |
30 // suspend. While coming out of suspend the display state may be updating. This | 30 // suspend. While coming out of suspend the display state may be updating. This |
31 // is used to wait until the hardware had a chance to update the display state | 31 // is used to wait until the hardware had a chance to update the display state |
32 // such that we read an up to date state. | 32 // such that we read an up to date state. |
33 const int kResumeDelayMs = 500; | 33 const int kResumeDelayMs = 500; |
34 | 34 |
| 35 void DoNothing(bool status) { |
| 36 } |
| 37 |
35 } // namespace | 38 } // namespace |
36 | 39 |
37 | 40 |
38 const int DisplayConfigurator::kSetDisplayPowerNoFlags = 0; | 41 const int DisplayConfigurator::kSetDisplayPowerNoFlags = 0; |
39 const int DisplayConfigurator::kSetDisplayPowerForceProbe = 1 << 0; | 42 const int DisplayConfigurator::kSetDisplayPowerForceProbe = 1 << 0; |
40 const int | 43 const int |
41 DisplayConfigurator::kSetDisplayPowerOnlyIfSingleInternalDisplay = 1 << 1; | 44 DisplayConfigurator::kSetDisplayPowerOnlyIfSingleInternalDisplay = 1 << 1; |
42 | 45 |
43 DisplayConfigurator::DisplayState::DisplayState() | 46 DisplayConfigurator::DisplayState::DisplayState() |
44 : display(NULL), | 47 : display(NULL), |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 force_configure_(false), | 456 force_configure_(false), |
454 next_display_protection_client_id_(1), | 457 next_display_protection_client_id_(1), |
455 display_externally_controlled_(false), | 458 display_externally_controlled_(false), |
456 layout_manager_(new DisplayLayoutManagerImpl(this)), | 459 layout_manager_(new DisplayLayoutManagerImpl(this)), |
457 weak_ptr_factory_(this) { | 460 weak_ptr_factory_(this) { |
458 } | 461 } |
459 | 462 |
460 DisplayConfigurator::~DisplayConfigurator() { | 463 DisplayConfigurator::~DisplayConfigurator() { |
461 if (native_display_delegate_) | 464 if (native_display_delegate_) |
462 native_display_delegate_->RemoveObserver(this); | 465 native_display_delegate_->RemoveObserver(this); |
| 466 |
| 467 CallAndClearInProgressCallbacks(false); |
| 468 CallAndClearQueuedCallbacks(false); |
463 } | 469 } |
464 | 470 |
465 void DisplayConfigurator::SetDelegateForTesting( | 471 void DisplayConfigurator::SetDelegateForTesting( |
466 scoped_ptr<NativeDisplayDelegate> display_delegate) { | 472 scoped_ptr<NativeDisplayDelegate> display_delegate) { |
467 DCHECK(!native_display_delegate_); | 473 DCHECK(!native_display_delegate_); |
468 | 474 |
469 native_display_delegate_ = display_delegate.Pass(); | 475 native_display_delegate_ = display_delegate.Pass(); |
470 configure_display_ = true; | 476 configure_display_ = true; |
471 } | 477 } |
472 | 478 |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
752 | 758 |
753 return false; | 759 return false; |
754 } | 760 } |
755 | 761 |
756 void DisplayConfigurator::PrepareForExit() { | 762 void DisplayConfigurator::PrepareForExit() { |
757 configure_display_ = false; | 763 configure_display_ = false; |
758 } | 764 } |
759 | 765 |
760 void DisplayConfigurator::SetDisplayPower( | 766 void DisplayConfigurator::SetDisplayPower( |
761 chromeos::DisplayPowerState power_state, | 767 chromeos::DisplayPowerState power_state, |
762 int flags) { | 768 int flags, |
763 if (!configure_display_ || display_externally_controlled_) | 769 const ConfigurationCallback& callback) { |
| 770 if (!configure_display_ || display_externally_controlled_) { |
| 771 callback.Run(false); |
764 return; | 772 return; |
| 773 } |
765 | 774 |
766 VLOG(1) << "SetDisplayPower: power_state=" | 775 VLOG(1) << "SetDisplayPower: power_state=" |
767 << DisplayPowerStateToString(power_state) << " flags=" << flags | 776 << DisplayPowerStateToString(power_state) << " flags=" << flags |
768 << ", configure timer=" | 777 << ", configure timer=" |
769 << (configure_timer_.IsRunning() ? "Running" : "Stopped"); | 778 << (configure_timer_.IsRunning() ? "Running" : "Stopped"); |
770 if (power_state == requested_power_state_ && | 779 if (power_state == requested_power_state_ && |
771 !(flags & kSetDisplayPowerForceProbe)) | 780 !(flags & kSetDisplayPowerForceProbe)) { |
| 781 callback.Run(true); |
772 return; | 782 return; |
| 783 } |
773 | 784 |
774 requested_power_state_ = power_state; | 785 requested_power_state_ = power_state; |
775 requested_power_state_change_ = true; | 786 requested_power_state_change_ = true; |
776 requested_power_flags_ = flags; | 787 requested_power_flags_ = flags; |
| 788 queued_configuration_callbacks_.push_back(callback); |
777 | 789 |
778 RunPendingConfiguration(); | 790 RunPendingConfiguration(); |
779 } | 791 } |
780 | 792 |
781 void DisplayConfigurator::SetDisplayMode(MultipleDisplayState new_state) { | 793 void DisplayConfigurator::SetDisplayMode(MultipleDisplayState new_state) { |
782 if (!configure_display_ || display_externally_controlled_) | 794 if (!configure_display_ || display_externally_controlled_) |
783 return; | 795 return; |
784 | 796 |
785 VLOG(1) << "SetDisplayMode: state=" | 797 VLOG(1) << "SetDisplayMode: state=" |
786 << MultipleDisplayStateToString(new_state); | 798 << MultipleDisplayStateToString(new_state); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
829 } | 841 } |
830 | 842 |
831 void DisplayConfigurator::SuspendDisplays() { | 843 void DisplayConfigurator::SuspendDisplays() { |
832 // If the display is off due to user inactivity and there's only a single | 844 // If the display is off due to user inactivity and there's only a single |
833 // internal display connected, switch to the all-on state before | 845 // internal display connected, switch to the all-on state before |
834 // suspending. This shouldn't be very noticeable to the user since the | 846 // suspending. This shouldn't be very noticeable to the user since the |
835 // backlight is off at this point, and doing this lets us resume directly | 847 // backlight is off at this point, and doing this lets us resume directly |
836 // into the "on" state, which greatly reduces resume times. | 848 // into the "on" state, which greatly reduces resume times. |
837 if (requested_power_state_ == chromeos::DISPLAY_POWER_ALL_OFF) { | 849 if (requested_power_state_ == chromeos::DISPLAY_POWER_ALL_OFF) { |
838 SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON, | 850 SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON, |
839 kSetDisplayPowerOnlyIfSingleInternalDisplay); | 851 kSetDisplayPowerOnlyIfSingleInternalDisplay, |
| 852 base::Bind(&DoNothing)); |
840 | 853 |
841 // We need to make sure that the monitor configuration we just did actually | 854 // We need to make sure that the monitor configuration we just did actually |
842 // completes before we return, because otherwise the X message could be | 855 // completes before we return, because otherwise the X message could be |
843 // racing with the HandleSuspendReadiness message. | 856 // racing with the HandleSuspendReadiness message. |
844 native_display_delegate_->SyncWithServer(); | 857 native_display_delegate_->SyncWithServer(); |
845 } | 858 } |
846 } | 859 } |
847 | 860 |
848 void DisplayConfigurator::ResumeDisplays() { | 861 void DisplayConfigurator::ResumeDisplays() { |
849 configure_timer_.Start( | 862 configure_timer_.Start( |
(...skipping 13 matching lines...) Expand all Loading... |
863 | 876 |
864 void DisplayConfigurator::RunPendingConfiguration() { | 877 void DisplayConfigurator::RunPendingConfiguration() { |
865 // Configuration task is currently running. Do not start a second | 878 // Configuration task is currently running. Do not start a second |
866 // configuration. | 879 // configuration. |
867 if (configuration_task_) | 880 if (configuration_task_) |
868 return; | 881 return; |
869 | 882 |
870 if (!ShouldRunConfigurationTask()) { | 883 if (!ShouldRunConfigurationTask()) { |
871 LOG(ERROR) << "Called RunPendingConfiguration without any changes" | 884 LOG(ERROR) << "Called RunPendingConfiguration without any changes" |
872 " requested"; | 885 " requested"; |
| 886 CallAndClearQueuedCallbacks(true); |
873 return; | 887 return; |
874 } | 888 } |
875 | 889 |
876 configuration_task_.reset(new UpdateDisplayConfigurationTask( | 890 configuration_task_.reset(new UpdateDisplayConfigurationTask( |
877 native_display_delegate_.get(), layout_manager_.get(), | 891 native_display_delegate_.get(), layout_manager_.get(), |
878 requested_display_state_, requested_power_state_, requested_power_flags_, | 892 requested_display_state_, requested_power_state_, requested_power_flags_, |
879 0, force_configure_, base::Bind(&DisplayConfigurator::OnConfigured, | 893 0, force_configure_, base::Bind(&DisplayConfigurator::OnConfigured, |
880 weak_ptr_factory_.GetWeakPtr()))); | 894 weak_ptr_factory_.GetWeakPtr()))); |
881 | 895 |
882 // Reset the flags before running the task; otherwise it may end up scheduling | 896 // Reset the flags before running the task; otherwise it may end up scheduling |
883 // another configuration. | 897 // another configuration. |
884 force_configure_ = false; | 898 force_configure_ = false; |
885 requested_power_flags_ = kSetDisplayPowerNoFlags; | 899 requested_power_flags_ = kSetDisplayPowerNoFlags; |
886 requested_power_state_change_ = false; | 900 requested_power_state_change_ = false; |
887 requested_display_state_ = MULTIPLE_DISPLAY_STATE_INVALID; | 901 requested_display_state_ = MULTIPLE_DISPLAY_STATE_INVALID; |
888 | 902 |
| 903 DCHECK(in_progress_configuration_callbacks_.empty()); |
| 904 in_progress_configuration_callbacks_.swap(queued_configuration_callbacks_); |
| 905 |
889 configuration_task_->Run(); | 906 configuration_task_->Run(); |
890 } | 907 } |
891 | 908 |
892 void DisplayConfigurator::OnConfigured( | 909 void DisplayConfigurator::OnConfigured( |
893 bool success, | 910 bool success, |
894 const std::vector<DisplayState>& displays, | 911 const std::vector<DisplayState>& displays, |
895 const gfx::Size& framebuffer_size, | 912 const gfx::Size& framebuffer_size, |
896 MultipleDisplayState new_display_state, | 913 MultipleDisplayState new_display_state, |
897 chromeos::DisplayPowerState new_power_state) { | 914 chromeos::DisplayPowerState new_power_state) { |
898 VLOG(1) << "OnConfigured: success=" << success << " new_display_state=" | 915 VLOG(1) << "OnConfigured: success=" << success << " new_display_state=" |
899 << MultipleDisplayStateToString(new_display_state) | 916 << MultipleDisplayStateToString(new_display_state) |
900 << " new_power_state=" << DisplayPowerStateToString(new_power_state); | 917 << " new_power_state=" << DisplayPowerStateToString(new_power_state); |
901 | 918 |
902 cached_displays_ = displays; | 919 cached_displays_ = displays; |
903 if (success) { | 920 if (success) { |
904 current_display_state_ = new_display_state; | 921 current_display_state_ = new_display_state; |
905 current_power_state_ = new_power_state; | 922 current_power_state_ = new_power_state; |
906 framebuffer_size_ = framebuffer_size; | 923 framebuffer_size_ = framebuffer_size; |
907 // If the requested power state hasn't changed then make sure that value | 924 // If the requested power state hasn't changed then make sure that value |
908 // gets updated as well since the last requested value may have been | 925 // gets updated as well since the last requested value may have been |
909 // dependent on certain conditions (ie: if only the internal monitor was | 926 // dependent on certain conditions (ie: if only the internal monitor was |
910 // present). | 927 // present). |
911 if (!requested_power_state_change_) | 928 if (!requested_power_state_change_) |
912 requested_power_state_ = new_power_state; | 929 requested_power_state_ = new_power_state; |
913 } | 930 } |
914 | 931 |
915 configuration_task_.reset(); | 932 configuration_task_.reset(); |
916 NotifyObservers(success, new_display_state); | 933 NotifyObservers(success, new_display_state); |
| 934 CallAndClearInProgressCallbacks(success); |
917 | 935 |
918 if (success && !configure_timer_.IsRunning() && | 936 if (success && !configure_timer_.IsRunning() && |
919 ShouldRunConfigurationTask()) { | 937 ShouldRunConfigurationTask()) { |
920 configure_timer_.Start(FROM_HERE, | 938 configure_timer_.Start(FROM_HERE, |
921 base::TimeDelta::FromMilliseconds(kConfigureDelayMs), | 939 base::TimeDelta::FromMilliseconds(kConfigureDelayMs), |
922 this, &DisplayConfigurator::RunPendingConfiguration); | 940 this, &DisplayConfigurator::RunPendingConfiguration); |
| 941 } else { |
| 942 // If a new configuration task isn't scheduled respond to all queued |
| 943 // callbacks (for example if requested state is current state). |
| 944 if (!configure_timer_.IsRunning()) |
| 945 CallAndClearQueuedCallbacks(success); |
923 } | 946 } |
924 } | 947 } |
925 | 948 |
926 bool DisplayConfigurator::ShouldRunConfigurationTask() const { | 949 bool DisplayConfigurator::ShouldRunConfigurationTask() const { |
927 if (force_configure_) | 950 if (force_configure_) |
928 return true; | 951 return true; |
929 | 952 |
930 // Schedule if there is a request to change the display state. | 953 // Schedule if there is a request to change the display state. |
931 if (requested_display_state_ != current_display_state_ && | 954 if (requested_display_state_ != current_display_state_ && |
932 requested_display_state_ != MULTIPLE_DISPLAY_STATE_INVALID) | 955 requested_display_state_ != MULTIPLE_DISPLAY_STATE_INVALID) |
933 return true; | 956 return true; |
934 | 957 |
935 // Schedule if there is a request to change the power state. | 958 // Schedule if there is a request to change the power state. |
936 if (requested_power_state_change_) | 959 if (requested_power_state_change_) |
937 return true; | 960 return true; |
938 | 961 |
939 return false; | 962 return false; |
940 } | 963 } |
941 | 964 |
| 965 void DisplayConfigurator::CallAndClearInProgressCallbacks(bool success) { |
| 966 for (const auto& callback : in_progress_configuration_callbacks_) |
| 967 callback.Run(success); |
| 968 |
| 969 in_progress_configuration_callbacks_.clear(); |
| 970 } |
| 971 |
| 972 void DisplayConfigurator::CallAndClearQueuedCallbacks(bool success) { |
| 973 for (const auto& callback : queued_configuration_callbacks_) |
| 974 callback.Run(success); |
| 975 |
| 976 queued_configuration_callbacks_.clear(); |
| 977 } |
| 978 |
942 void DisplayConfigurator::RestoreRequestedPowerStateAfterResume() { | 979 void DisplayConfigurator::RestoreRequestedPowerStateAfterResume() { |
943 // Force probing to ensure that we pick up any changes that were made while | 980 // Force probing to ensure that we pick up any changes that were made while |
944 // the system was suspended. | 981 // the system was suspended. |
945 SetDisplayPower(requested_power_state_, kSetDisplayPowerForceProbe); | 982 SetDisplayPower(requested_power_state_, kSetDisplayPowerForceProbe, |
| 983 base::Bind(&DoNothing)); |
946 } | 984 } |
947 | 985 |
948 void DisplayConfigurator::NotifyObservers( | 986 void DisplayConfigurator::NotifyObservers( |
949 bool success, | 987 bool success, |
950 MultipleDisplayState attempted_state) { | 988 MultipleDisplayState attempted_state) { |
951 if (success) { | 989 if (success) { |
952 FOR_EACH_OBSERVER( | 990 FOR_EACH_OBSERVER( |
953 Observer, observers_, OnDisplayModeChanged(cached_displays_)); | 991 Observer, observers_, OnDisplayModeChanged(cached_displays_)); |
954 } else { | 992 } else { |
955 FOR_EACH_OBSERVER( | 993 FOR_EACH_OBSERVER( |
956 Observer, observers_, OnDisplayModeChangeFailed(attempted_state)); | 994 Observer, observers_, OnDisplayModeChangeFailed(attempted_state)); |
957 } | 995 } |
958 } | 996 } |
959 | 997 |
960 } // namespace ui | 998 } // namespace ui |
OLD | NEW |