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"
15 UpdateDisplayConfigurationTask::UpdateDisplayConfigurationTask(
16 NativeDisplayDelegate
* delegate
,
17 DisplayLayoutManager
* layout_manager
,
18 MultipleDisplayState new_display_state
,
19 chromeos::DisplayPowerState new_power_state
,
21 uint32_t background_color_argb
,
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
),
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
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()));
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
);
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();
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
)
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_
||
116 new_display_state_
= MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED
;
117 EnterState(base::Bind(
118 &UpdateDisplayConfigurationTask::OnEnableSoftwareMirroring
,
119 weak_ptr_factory_
.GetWeakPtr()));
123 success
= layout_manager_
->GetDisplayState() ==
124 MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED
;
125 enable_software_mirroring
= 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(
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_
)
163 if (cached_displays_
.size() == 1 &&
164 cached_displays_
[0]->type() == DISPLAY_CONNECTION_TYPE_INTERNAL
)
168 DisplayConfigurator::kSetDisplayPowerOnlyIfSingleInternalDisplay
))
171 if (new_display_state_
!= layout_manager_
->GetDisplayState())
177 MultipleDisplayState
UpdateDisplayConfigurationTask::ChooseDisplayState()
179 int num_on_displays
=
180 GetDisplayPower(cached_displays_
, new_power_state_
, NULL
);
181 switch (cached_displays_
.size()) {
183 return MULTIPLE_DISPLAY_STATE_HEADLESS
;
185 return MULTIPLE_DISPLAY_STATE_SINGLE
;
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
199 return layout_manager_
->GetStateController()->GetStateForDisplayIds(
205 return MULTIPLE_DISPLAY_STATE_INVALID
;