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/configure_displays_task.h"
7 #include "base/auto_reset.h"
9 #include "ui/display/types/display_snapshot.h"
10 #include "ui/display/types/native_display_delegate.h"
16 // Find the next best mode after |display_mode|. If none can be found return
18 const DisplayMode
* FindNextMode(const DisplaySnapshot
& display_state
,
19 const DisplayMode
* display_mode
) {
23 int best_mode_pixels
= 0;
24 const DisplayMode
* best_mode
= nullptr;
25 int current_mode_pixels
= display_mode
->size().GetArea();
26 for (const DisplayMode
* mode
: display_state
.modes()) {
27 int pixel_count
= mode
->size().GetArea();
28 if (pixel_count
< current_mode_pixels
&& pixel_count
> best_mode_pixels
) {
30 best_mode_pixels
= pixel_count
;
39 DisplayConfigureRequest::DisplayConfigureRequest(DisplaySnapshot
* display
,
40 const DisplayMode
* mode
,
41 const gfx::Point
& origin
)
42 : display(display
), mode(mode
), origin(origin
) {
45 ConfigureDisplaysTask::ConfigureDisplaysTask(
46 NativeDisplayDelegate
* delegate
,
47 const std::vector
<DisplayConfigureRequest
>& requests
,
48 const ResponseCallback
& callback
)
49 : delegate_(delegate
),
52 is_configuring_(false),
53 num_displays_configured_(0),
54 task_status_(SUCCESS
),
55 weak_ptr_factory_(this) {
56 for (size_t i
= 0; i
< requests_
.size(); ++i
)
57 pending_request_indexes_
.push(i
);
60 ConfigureDisplaysTask::~ConfigureDisplaysTask() {
63 void ConfigureDisplaysTask::Run() {
64 // Synchronous configurators will recursively call Run(). In that case just
65 // defer their call to the next iteration in the while-loop. This is done to
66 // guard against stack overflows if the display has a large list of broken
72 base::AutoReset
<bool> recursivity_guard(&is_configuring_
, true);
73 while (!pending_request_indexes_
.empty()) {
74 size_t index
= pending_request_indexes_
.front();
75 DisplayConfigureRequest
* request
= &requests_
[index
];
76 pending_request_indexes_
.pop();
77 delegate_
->Configure(*request
->display
, request
->mode
, request
->origin
,
78 base::Bind(&ConfigureDisplaysTask::OnConfigured
,
79 weak_ptr_factory_
.GetWeakPtr(), index
));
83 // Nothing should be modified after the |callback_| is called since the
84 // task may be deleted in the callback.
85 if (num_displays_configured_
== requests_
.size())
86 callback_
.Run(task_status_
);
89 void ConfigureDisplaysTask::OnConfigured(size_t index
, bool success
) {
90 DisplayConfigureRequest
* request
= &requests_
[index
];
91 VLOG(2) << "Configured status=" << success
92 << " display=" << request
->display
->display_id()
93 << " origin=" << request
->origin
.ToString()
94 << " mode=" << (request
->mode
? request
->mode
->ToString() : "null");
96 request
->mode
= FindNextMode(*request
->display
, request
->mode
);
98 pending_request_indexes_
.push(index
);
99 if (task_status_
== SUCCESS
)
100 task_status_
= PARTIAL_SUCCESS
;
106 request
->display
->set_current_mode(request
->mode
);
107 request
->display
->set_origin(request
->origin
);
110 num_displays_configured_
++;
112 task_status_
= ERROR
;