| Index: ui/display/chromeos/update_display_configuration_task.cc
|
| diff --git a/ui/display/chromeos/update_display_configuration_task.cc b/ui/display/chromeos/update_display_configuration_task.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..fea9214dc021c899b1aac6c41c4eec548b683a29
|
| --- /dev/null
|
| +++ b/ui/display/chromeos/update_display_configuration_task.cc
|
| @@ -0,0 +1,210 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "ui/display/chromeos/update_display_configuration_task.h"
|
| +
|
| +#include "ui/display/chromeos/configure_displays_task.h"
|
| +#include "ui/display/chromeos/display_util.h"
|
| +#include "ui/display/types/display_snapshot.h"
|
| +#include "ui/display/types/native_display_delegate.h"
|
| +
|
| +namespace ui {
|
| +
|
| +UpdateDisplayConfigurationTask::UpdateDisplayConfigurationTask(
|
| + NativeDisplayDelegate* delegate,
|
| + DisplayConfigurator::DisplayLayoutManager* layout_manager,
|
| + MultipleDisplayState new_display_state,
|
| + chromeos::DisplayPowerState new_power_state,
|
| + int power_flags,
|
| + uint32_t background_color_argb,
|
| + bool force_configure,
|
| + const ResponseCallback& callback)
|
| + : delegate_(delegate),
|
| + layout_manager_(layout_manager),
|
| + new_display_state_(new_display_state),
|
| + new_power_state_(new_power_state),
|
| + power_flags_(power_flags),
|
| + background_color_argb_(background_color_argb),
|
| + force_configure_(force_configure),
|
| + callback_(callback),
|
| + force_dpms_(false),
|
| + weak_ptr_factory_(this) {
|
| + delegate_->GrabServer();
|
| +}
|
| +
|
| +UpdateDisplayConfigurationTask::~UpdateDisplayConfigurationTask() {
|
| + delegate_->UngrabServer();
|
| +}
|
| +
|
| +void UpdateDisplayConfigurationTask::Run() {
|
| + delegate_->GetDisplays(
|
| + base::Bind(&UpdateDisplayConfigurationTask::OnDisplaysUpdated,
|
| + weak_ptr_factory_.GetWeakPtr()));
|
| +}
|
| +
|
| +void UpdateDisplayConfigurationTask::OnDisplaysUpdated(
|
| + const std::vector<DisplaySnapshot*>& displays) {
|
| + cached_displays_ = layout_manager_->ParseDisplays(displays);
|
| +
|
| + if (cached_displays_.size() > 1 && background_color_argb_)
|
| + delegate_->SetBackgroundColor(background_color_argb_);
|
| +
|
| + // If the user hasn't requested a display state, update it using the requested
|
| + // power state.
|
| + if (new_display_state_ == MULTIPLE_DISPLAY_STATE_INVALID)
|
| + new_display_state_ = ChooseDisplayState();
|
| +
|
| + VLOG(1) << "OnDisplaysUpdated: new_display_state="
|
| + << MultipleDisplayStateToString(new_display_state_)
|
| + << " new_power_state=" << DisplayPowerStateToString(new_power_state_)
|
| + << " flags=" << power_flags_
|
| + << " force_configure=" << force_configure_
|
| + << " display_count=" << cached_displays_.size();
|
| + // If there has been any change in the requested power state and the displays
|
| + // aren't being turned off force a change in DPMS state.
|
| + force_dpms_ = ShouldForceDpms() && ShouldConfigure();
|
| +
|
| + if (ShouldConfigure()) {
|
| + EnterState(base::Bind(&UpdateDisplayConfigurationTask::OnStateEntered,
|
| + weak_ptr_factory_.GetWeakPtr()));
|
| + } else {
|
| + // If we don't have to configure then we're sticking with the old
|
| + // configuration. Update it such that it reflects in the reported value.
|
| + new_power_state_ = layout_manager_->GetPowerState();
|
| + FinishConfiguration(true);
|
| + }
|
| +}
|
| +
|
| +void UpdateDisplayConfigurationTask::EnterState(
|
| + const ConfigureDisplaysTask::ResponseCallback& callback) {
|
| + VLOG(2) << "EnterState";
|
| + std::vector<DisplayConfigureRequest> requests;
|
| + if (!layout_manager_->GetDisplayLayout(cached_displays_, new_display_state_,
|
| + new_power_state_, &requests,
|
| + &framebuffer_size_)) {
|
| + callback.Run(ConfigureDisplaysTask::ERROR);
|
| + return;
|
| + }
|
| +
|
| + if (!requests.empty()) {
|
| + delegate_->CreateFrameBuffer(framebuffer_size_);
|
| + configure_task_.reset(
|
| + new ConfigureDisplaysTask(delegate_, requests, callback));
|
| + configure_task_->Run();
|
| + } else {
|
| + VLOG(2) << "No displays";
|
| + callback.Run(ConfigureDisplaysTask::SUCCESS);
|
| + }
|
| +}
|
| +
|
| +void UpdateDisplayConfigurationTask::OnStateEntered(
|
| + ConfigureDisplaysTask::Status status) {
|
| + bool success = status != ConfigureDisplaysTask::ERROR;
|
| + if (new_display_state_ == MULTIPLE_DISPLAY_STATE_DUAL_MIRROR &&
|
| + status == ConfigureDisplaysTask::PARTIAL_SUCCESS)
|
| + success = false;
|
| +
|
| + if (layout_manager_->GetSoftwareMirroringController()) {
|
| + bool enable_software_mirroring = false;
|
| + if (!success && new_display_state_ == MULTIPLE_DISPLAY_STATE_DUAL_MIRROR) {
|
| + if (layout_manager_->GetDisplayState() !=
|
| + MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED ||
|
| + layout_manager_->GetPowerState() != new_power_state_) {
|
| + new_display_state_ = MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED;
|
| + EnterState(base::Bind(
|
| + &UpdateDisplayConfigurationTask::OnEnableSoftwareMirroring,
|
| + weak_ptr_factory_.GetWeakPtr()));
|
| + return;
|
| + }
|
| +
|
| + success = layout_manager_->GetDisplayState() ==
|
| + MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED;
|
| + enable_software_mirroring = success;
|
| + if (success)
|
| + new_display_state_ = MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED;
|
| + }
|
| +
|
| + layout_manager_->GetSoftwareMirroringController()->SetSoftwareMirroring(
|
| + enable_software_mirroring);
|
| + }
|
| +
|
| + FinishConfiguration(success);
|
| +}
|
| +
|
| +void UpdateDisplayConfigurationTask::OnEnableSoftwareMirroring(
|
| + ConfigureDisplaysTask::Status status) {
|
| + bool success = status != ConfigureDisplaysTask::ERROR;
|
| + layout_manager_->GetSoftwareMirroringController()->SetSoftwareMirroring(
|
| + success);
|
| + FinishConfiguration(success);
|
| +}
|
| +
|
| +void UpdateDisplayConfigurationTask::FinishConfiguration(bool success) {
|
| + if (success && force_dpms_)
|
| + delegate_->ForceDPMSOn();
|
| +
|
| + callback_.Run(success, cached_displays_, framebuffer_size_,
|
| + new_display_state_, new_power_state_);
|
| +}
|
| +
|
| +bool UpdateDisplayConfigurationTask::ShouldForceDpms() const {
|
| + return new_power_state_ != chromeos::DISPLAY_POWER_ALL_OFF &&
|
| + (layout_manager_->GetPowerState() != new_power_state_ ||
|
| + (power_flags_ & DisplayConfigurator::kSetDisplayPowerForceProbe));
|
| +}
|
| +
|
| +bool UpdateDisplayConfigurationTask::ShouldConfigure() const {
|
| + if (force_configure_)
|
| + return true;
|
| +
|
| + if (cached_displays_.size() == 1 &&
|
| + cached_displays_[0].display->type() == DISPLAY_CONNECTION_TYPE_INTERNAL)
|
| + return true;
|
| +
|
| + if (!(power_flags_ &
|
| + DisplayConfigurator::kSetDisplayPowerOnlyIfSingleInternalDisplay))
|
| + return true;
|
| +
|
| + if (new_display_state_ != layout_manager_->GetDisplayState())
|
| + return true;
|
| +
|
| + return false;
|
| +}
|
| +
|
| +MultipleDisplayState UpdateDisplayConfigurationTask::ChooseDisplayState()
|
| + const {
|
| + int num_on_displays =
|
| + GetDisplayPower(cached_displays_, new_power_state_, NULL);
|
| + switch (cached_displays_.size()) {
|
| + case 0:
|
| + return MULTIPLE_DISPLAY_STATE_HEADLESS;
|
| + case 1:
|
| + return MULTIPLE_DISPLAY_STATE_SINGLE;
|
| + default: {
|
| + if (num_on_displays == 1) {
|
| + // If only one display is currently turned on, return the "single"
|
| + // state so that its native mode will be used.
|
| + return MULTIPLE_DISPLAY_STATE_SINGLE;
|
| + }
|
| + if (num_on_displays >= 3) {
|
| + return MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED;
|
| + } else if (cached_displays_.size() == 2) {
|
| + if (!layout_manager_->GetStateController())
|
| + return MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED;
|
| + // With either both displays on or both displays off, use one of the
|
| + // dual modes.
|
| + std::vector<int64_t> display_ids;
|
| + for (size_t i = 0; i < cached_displays_.size(); ++i)
|
| + display_ids.push_back(cached_displays_[i].display->display_id());
|
| +
|
| + return layout_manager_->GetStateController()->GetStateForDisplayIds(
|
| + display_ids);
|
| + }
|
| + NOTREACHED();
|
| + }
|
| + }
|
| + return MULTIPLE_DISPLAY_STATE_INVALID;
|
| +}
|
| +
|
| +} // namespace ui
|
|
|