Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ui / display / chromeos / update_display_configuration_task.cc
blob335c661bb1154a5ceee36528b667bf005cf17867
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
3 // found in the LICENSE file.
5 #include "ui/display/chromeos/update_display_configuration_task.h"
7 #include "ui/display/chromeos/configure_displays_task.h"
8 #include "ui/display/chromeos/display_layout_manager.h"
9 #include "ui/display/chromeos/display_util.h"
10 #include "ui/display/types/display_snapshot.h"
11 #include "ui/display/types/native_display_delegate.h"
13 namespace ui {
15 UpdateDisplayConfigurationTask::UpdateDisplayConfigurationTask(
16 NativeDisplayDelegate* delegate,
17 DisplayLayoutManager* layout_manager,
18 MultipleDisplayState new_display_state,
19 chromeos::DisplayPowerState new_power_state,
20 int power_flags,
21 uint32_t background_color_argb,
22 bool force_configure,
23 const ResponseCallback& callback)
24 : delegate_(delegate),
25 layout_manager_(layout_manager),
26 new_display_state_(new_display_state),
27 new_power_state_(new_power_state),
28 power_flags_(power_flags),
29 background_color_argb_(background_color_argb),
30 force_configure_(force_configure),
31 callback_(callback),
32 force_dpms_(false),
33 weak_ptr_factory_(this) {
34 delegate_->GrabServer();
37 UpdateDisplayConfigurationTask::~UpdateDisplayConfigurationTask() {
38 delegate_->UngrabServer();
41 void UpdateDisplayConfigurationTask::Run() {
42 delegate_->GetDisplays(
43 base::Bind(&UpdateDisplayConfigurationTask::OnDisplaysUpdated,
44 weak_ptr_factory_.GetWeakPtr()));
47 void UpdateDisplayConfigurationTask::OnDisplaysUpdated(
48 const std::vector<DisplaySnapshot*>& displays) {
49 cached_displays_ = displays;
51 if (cached_displays_.size() > 1 && background_color_argb_)
52 delegate_->SetBackgroundColor(background_color_argb_);
54 // If the user hasn't requested a display state, update it using the requested
55 // power state.
56 if (new_display_state_ == MULTIPLE_DISPLAY_STATE_INVALID)
57 new_display_state_ = ChooseDisplayState();
59 VLOG(1) << "OnDisplaysUpdated: new_display_state="
60 << MultipleDisplayStateToString(new_display_state_)
61 << " new_power_state=" << DisplayPowerStateToString(new_power_state_)
62 << " flags=" << power_flags_
63 << " force_configure=" << force_configure_
64 << " display_count=" << cached_displays_.size();
65 // If there has been any change in the requested power state and the displays
66 // aren't being turned off force a change in DPMS state.
67 force_dpms_ = ShouldForceDpms() && ShouldConfigure();
69 if (ShouldConfigure()) {
70 EnterState(base::Bind(&UpdateDisplayConfigurationTask::OnStateEntered,
71 weak_ptr_factory_.GetWeakPtr()));
72 } else {
73 // If we don't have to configure then we're sticking with the old
74 // configuration. Update it such that it reflects in the reported value.
75 new_power_state_ = layout_manager_->GetPowerState();
76 FinishConfiguration(true);
80 void UpdateDisplayConfigurationTask::EnterState(
81 const ConfigureDisplaysTask::ResponseCallback& callback) {
82 VLOG(2) << "EnterState";
83 std::vector<DisplayConfigureRequest> requests;
84 if (!layout_manager_->GetDisplayLayout(cached_displays_, new_display_state_,
85 new_power_state_, &requests,
86 &framebuffer_size_)) {
87 callback.Run(ConfigureDisplaysTask::ERROR);
88 return;
90 if (!requests.empty()) {
91 DCHECK(!framebuffer_size_.IsEmpty());
92 delegate_->CreateFrameBuffer(framebuffer_size_);
93 configure_task_.reset(
94 new ConfigureDisplaysTask(delegate_, requests, callback));
95 configure_task_->Run();
96 } else {
97 VLOG(2) << "No displays";
98 callback.Run(ConfigureDisplaysTask::SUCCESS);
102 void UpdateDisplayConfigurationTask::OnStateEntered(
103 ConfigureDisplaysTask::Status status) {
104 bool success = status != ConfigureDisplaysTask::ERROR;
105 if (new_display_state_ == MULTIPLE_DISPLAY_STATE_DUAL_MIRROR &&
106 status == ConfigureDisplaysTask::PARTIAL_SUCCESS)
107 success = false;
109 if (layout_manager_->GetSoftwareMirroringController()) {
110 bool enable_software_mirroring = false;
111 if (!success && new_display_state_ == MULTIPLE_DISPLAY_STATE_DUAL_MIRROR) {
112 if (layout_manager_->GetDisplayState() !=
113 MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED ||
114 layout_manager_->GetPowerState() != new_power_state_ ||
115 force_configure_) {
116 new_display_state_ = MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED;
117 EnterState(base::Bind(
118 &UpdateDisplayConfigurationTask::OnEnableSoftwareMirroring,
119 weak_ptr_factory_.GetWeakPtr()));
120 return;
123 success = layout_manager_->GetDisplayState() ==
124 MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED;
125 enable_software_mirroring = success;
126 if (success)
127 new_display_state_ = MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED;
130 layout_manager_->GetSoftwareMirroringController()->SetSoftwareMirroring(
131 enable_software_mirroring);
134 FinishConfiguration(success);
137 void UpdateDisplayConfigurationTask::OnEnableSoftwareMirroring(
138 ConfigureDisplaysTask::Status status) {
139 bool success = status != ConfigureDisplaysTask::ERROR;
140 layout_manager_->GetSoftwareMirroringController()->SetSoftwareMirroring(
141 success);
142 FinishConfiguration(success);
145 void UpdateDisplayConfigurationTask::FinishConfiguration(bool success) {
146 if (success && force_dpms_)
147 delegate_->ForceDPMSOn();
149 callback_.Run(success, cached_displays_, framebuffer_size_,
150 new_display_state_, new_power_state_);
153 bool UpdateDisplayConfigurationTask::ShouldForceDpms() const {
154 return new_power_state_ != chromeos::DISPLAY_POWER_ALL_OFF &&
155 (layout_manager_->GetPowerState() != new_power_state_ ||
156 (power_flags_ & DisplayConfigurator::kSetDisplayPowerForceProbe));
159 bool UpdateDisplayConfigurationTask::ShouldConfigure() const {
160 if (force_configure_)
161 return true;
163 if (cached_displays_.size() == 1 &&
164 cached_displays_[0]->type() == DISPLAY_CONNECTION_TYPE_INTERNAL)
165 return true;
167 if (!(power_flags_ &
168 DisplayConfigurator::kSetDisplayPowerOnlyIfSingleInternalDisplay))
169 return true;
171 if (new_display_state_ != layout_manager_->GetDisplayState())
172 return true;
174 return false;
177 MultipleDisplayState UpdateDisplayConfigurationTask::ChooseDisplayState()
178 const {
179 int num_on_displays =
180 GetDisplayPower(cached_displays_, new_power_state_, NULL);
181 switch (cached_displays_.size()) {
182 case 0:
183 return MULTIPLE_DISPLAY_STATE_HEADLESS;
184 case 1:
185 return MULTIPLE_DISPLAY_STATE_SINGLE;
186 default: {
187 if (num_on_displays == 1) {
188 // If only one display is currently turned on, return the "single"
189 // state so that its native mode will be used.
190 return MULTIPLE_DISPLAY_STATE_SINGLE;
192 if (num_on_displays >= 3) {
193 return MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED;
194 } else if (cached_displays_.size() == 2) {
195 if (!layout_manager_->GetStateController())
196 return MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED;
197 // With either both displays on or both displays off, use one of the
198 // dual modes.
199 return layout_manager_->GetStateController()->GetStateForDisplayIds(
200 cached_displays_);
202 NOTREACHED();
205 return MULTIPLE_DISPLAY_STATE_INVALID;
208 } // namespace ui