| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "ui/display/chromeos/update_display_configuration_task.h" | |
| 6 | |
| 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" | |
| 12 | |
| 13 namespace ui { | |
| 14 | |
| 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(); | |
| 35 } | |
| 36 | |
| 37 UpdateDisplayConfigurationTask::~UpdateDisplayConfigurationTask() { | |
| 38 delegate_->UngrabServer(); | |
| 39 } | |
| 40 | |
| 41 void UpdateDisplayConfigurationTask::Run() { | |
| 42 delegate_->GetDisplays( | |
| 43 base::Bind(&UpdateDisplayConfigurationTask::OnDisplaysUpdated, | |
| 44 weak_ptr_factory_.GetWeakPtr())); | |
| 45 } | |
| 46 | |
| 47 void UpdateDisplayConfigurationTask::OnDisplaysUpdated( | |
| 48 const std::vector<DisplaySnapshot*>& displays) { | |
| 49 cached_displays_ = displays; | |
| 50 | |
| 51 // Add virtual displays after retrieving the physical displays from the NDD. | |
| 52 cached_displays_.insert(cached_displays_.end(), | |
| 53 virtual_display_snapshots_.begin(), | |
| 54 virtual_display_snapshots_.end()); | |
| 55 | |
| 56 if (cached_displays_.size() > 1 && background_color_argb_) | |
| 57 delegate_->SetBackgroundColor(background_color_argb_); | |
| 58 | |
| 59 // If the user hasn't requested a display state, update it using the requested | |
| 60 // power state. | |
| 61 if (new_display_state_ == MULTIPLE_DISPLAY_STATE_INVALID) | |
| 62 new_display_state_ = ChooseDisplayState(); | |
| 63 | |
| 64 VLOG(1) << "OnDisplaysUpdated: new_display_state=" | |
| 65 << MultipleDisplayStateToString(new_display_state_) | |
| 66 << " new_power_state=" << DisplayPowerStateToString(new_power_state_) | |
| 67 << " flags=" << power_flags_ | |
| 68 << " force_configure=" << force_configure_ | |
| 69 << " display_count=" << cached_displays_.size(); | |
| 70 // If there has been any change in the requested power state and the displays | |
| 71 // aren't being turned off force a change in DPMS state. | |
| 72 force_dpms_ = ShouldForceDpms() && ShouldConfigure(); | |
| 73 | |
| 74 if (ShouldConfigure()) { | |
| 75 EnterState(base::Bind(&UpdateDisplayConfigurationTask::OnStateEntered, | |
| 76 weak_ptr_factory_.GetWeakPtr())); | |
| 77 } else { | |
| 78 // If we don't have to configure then we're sticking with the old | |
| 79 // configuration. Update it such that it reflects in the reported value. | |
| 80 new_power_state_ = layout_manager_->GetPowerState(); | |
| 81 FinishConfiguration(true); | |
| 82 } | |
| 83 } | |
| 84 | |
| 85 void UpdateDisplayConfigurationTask::EnterState( | |
| 86 const ConfigureDisplaysTask::ResponseCallback& callback) { | |
| 87 VLOG(2) << "EnterState"; | |
| 88 std::vector<DisplayConfigureRequest> requests; | |
| 89 if (!layout_manager_->GetDisplayLayout(cached_displays_, new_display_state_, | |
| 90 new_power_state_, &requests, | |
| 91 &framebuffer_size_)) { | |
| 92 callback.Run(ConfigureDisplaysTask::ERROR); | |
| 93 return; | |
| 94 } | |
| 95 if (!requests.empty()) { | |
| 96 DCHECK(!framebuffer_size_.IsEmpty()); | |
| 97 delegate_->CreateFrameBuffer(framebuffer_size_); | |
| 98 configure_task_.reset( | |
| 99 new ConfigureDisplaysTask(delegate_, requests, callback)); | |
| 100 configure_task_->Run(); | |
| 101 } else { | |
| 102 VLOG(2) << "No displays"; | |
| 103 callback.Run(ConfigureDisplaysTask::SUCCESS); | |
| 104 } | |
| 105 } | |
| 106 | |
| 107 void UpdateDisplayConfigurationTask::OnStateEntered( | |
| 108 ConfigureDisplaysTask::Status status) { | |
| 109 bool success = status != ConfigureDisplaysTask::ERROR; | |
| 110 if (new_display_state_ == MULTIPLE_DISPLAY_STATE_DUAL_MIRROR && | |
| 111 status == ConfigureDisplaysTask::PARTIAL_SUCCESS) | |
| 112 success = false; | |
| 113 | |
| 114 if (layout_manager_->GetSoftwareMirroringController()) { | |
| 115 bool enable_software_mirroring = false; | |
| 116 if (!success && new_display_state_ == MULTIPLE_DISPLAY_STATE_DUAL_MIRROR) { | |
| 117 if (layout_manager_->GetDisplayState() != | |
| 118 MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED || | |
| 119 layout_manager_->GetPowerState() != new_power_state_ || | |
| 120 force_configure_) { | |
| 121 new_display_state_ = MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED; | |
| 122 EnterState(base::Bind( | |
| 123 &UpdateDisplayConfigurationTask::OnEnableSoftwareMirroring, | |
| 124 weak_ptr_factory_.GetWeakPtr())); | |
| 125 return; | |
| 126 } | |
| 127 | |
| 128 success = layout_manager_->GetDisplayState() == | |
| 129 MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED; | |
| 130 enable_software_mirroring = success; | |
| 131 if (success) | |
| 132 new_display_state_ = MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED; | |
| 133 } | |
| 134 | |
| 135 layout_manager_->GetSoftwareMirroringController()->SetSoftwareMirroring( | |
| 136 enable_software_mirroring); | |
| 137 } | |
| 138 | |
| 139 FinishConfiguration(success); | |
| 140 } | |
| 141 | |
| 142 void UpdateDisplayConfigurationTask::OnEnableSoftwareMirroring( | |
| 143 ConfigureDisplaysTask::Status status) { | |
| 144 bool success = status != ConfigureDisplaysTask::ERROR; | |
| 145 layout_manager_->GetSoftwareMirroringController()->SetSoftwareMirroring( | |
| 146 success); | |
| 147 FinishConfiguration(success); | |
| 148 } | |
| 149 | |
| 150 void UpdateDisplayConfigurationTask::FinishConfiguration(bool success) { | |
| 151 if (success && force_dpms_) | |
| 152 delegate_->ForceDPMSOn(); | |
| 153 | |
| 154 callback_.Run(success, cached_displays_, framebuffer_size_, | |
| 155 new_display_state_, new_power_state_); | |
| 156 } | |
| 157 | |
| 158 bool UpdateDisplayConfigurationTask::ShouldForceDpms() const { | |
| 159 return new_power_state_ != chromeos::DISPLAY_POWER_ALL_OFF && | |
| 160 (layout_manager_->GetPowerState() != new_power_state_ || | |
| 161 (power_flags_ & DisplayConfigurator::kSetDisplayPowerForceProbe)); | |
| 162 } | |
| 163 | |
| 164 bool UpdateDisplayConfigurationTask::ShouldConfigure() const { | |
| 165 if (force_configure_) | |
| 166 return true; | |
| 167 | |
| 168 if (cached_displays_.size() == 1 && | |
| 169 cached_displays_[0]->type() == DISPLAY_CONNECTION_TYPE_INTERNAL) | |
| 170 return true; | |
| 171 | |
| 172 if (!(power_flags_ & | |
| 173 DisplayConfigurator::kSetDisplayPowerOnlyIfSingleInternalDisplay)) | |
| 174 return true; | |
| 175 | |
| 176 if (new_display_state_ != layout_manager_->GetDisplayState()) | |
| 177 return true; | |
| 178 | |
| 179 return false; | |
| 180 } | |
| 181 | |
| 182 MultipleDisplayState UpdateDisplayConfigurationTask::ChooseDisplayState() | |
| 183 const { | |
| 184 int num_displays = cached_displays_.size(); | |
| 185 int num_on_displays = | |
| 186 GetDisplayPower(cached_displays_, new_power_state_, nullptr); | |
| 187 | |
| 188 if (num_displays == 0) | |
| 189 return MULTIPLE_DISPLAY_STATE_HEADLESS; | |
| 190 | |
| 191 if (num_displays == 1 || num_on_displays == 1) { | |
| 192 // If only one display is currently turned on, return the "single" state | |
| 193 // so that its native mode will be used. | |
| 194 return MULTIPLE_DISPLAY_STATE_SINGLE; | |
| 195 } | |
| 196 | |
| 197 if (num_displays == 2 || num_on_displays == 2) { | |
| 198 // Try to use the saved configuration; otherwise, default to extended. | |
| 199 DisplayConfigurator::StateController* state_controller = | |
| 200 layout_manager_->GetStateController(); | |
| 201 | |
| 202 if (!state_controller) | |
| 203 return MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED; | |
| 204 return state_controller->GetStateForDisplayIds(cached_displays_); | |
| 205 } | |
| 206 | |
| 207 if (num_displays >= 3) { | |
| 208 // 3+ displays are always extended | |
| 209 return MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED; | |
| 210 } | |
| 211 | |
| 212 return MULTIPLE_DISPLAY_STATE_INVALID; | |
| 213 } | |
| 214 | |
| 215 } // namespace ui | |
| OLD | NEW |