Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(220)

Side by Side Diff: services/ui/display/platform_screen_ozone.cc

Issue 2549503002: Rename PlatformScreen to ScreenManager. (Closed)
Patch Set: Rebase. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 "services/ui/display/platform_screen_ozone.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/command_line.h"
11 #include "base/memory/ptr_util.h"
12 #include "base/sys_info.h"
13 #include "base/threading/thread_task_runner_handle.h"
14 #include "services/service_manager/public/cpp/interface_registry.h"
15 #include "third_party/skia/include/core/SkColor.h"
16 #include "ui/display/types/display_snapshot.h"
17 #include "ui/display/types/native_display_delegate.h"
18 #include "ui/gfx/geometry/rect.h"
19 #include "ui/ozone/public/ozone_platform.h"
20
21 namespace display {
22 namespace {
23
24 // Needed for DisplayConfigurator::ForceInitialConfigure.
25 const SkColor kChromeOsBootColor = SkColorSetRGB(0xfe, 0xfe, 0xfe);
26
27 const float kInchInMm = 25.4f;
28
29 float ComputeDisplayDPI(const gfx::Size& pixel_size,
30 const gfx::Size& physical_size) {
31 // The physical_size is broken for some devices, return standard DPI. See
32 // crbug.com/669554.
33 if (physical_size.IsEmpty()) {
34 LOG(ERROR) << "Display has empty phsical_size";
35 return 96.0f;
36 }
37
38 return (pixel_size.width() / static_cast<float>(physical_size.width())) *
39 kInchInMm;
40 }
41
42 // Finds the device scale factor based on the display DPI. Will use forced
43 // device scale factor if provided via command line.
44 float FindDeviceScaleFactor(float dpi) {
45 if (Display::HasForceDeviceScaleFactor())
46 return Display::GetForcedDeviceScaleFactor();
47
48 // TODO(kylechar): If dpi > 150 then ash uses 1.25 now. Ignoring that for now.
49 if (dpi > 200.0)
50 return 2.0f;
51 else
52 return 1.0f;
53 }
54
55 } // namespace
56
57 // static
58 std::unique_ptr<PlatformScreen> PlatformScreen::Create() {
59 return base::MakeUnique<PlatformScreenOzone>();
60 }
61
62 PlatformScreenOzone::PlatformScreenOzone() {}
63
64 PlatformScreenOzone::~PlatformScreenOzone() {
65 // We are shutting down and don't want to make anymore display changes.
66 fake_display_controller_ = nullptr;
67 display_configurator_.RemoveObserver(this);
68 }
69
70 void PlatformScreenOzone::AddInterfaces(
71 service_manager::InterfaceRegistry* registry) {
72 registry->AddInterface<mojom::DisplayController>(this);
73 registry->AddInterface<mojom::TestDisplayController>(this);
74 }
75
76 void PlatformScreenOzone::Init(PlatformScreenDelegate* delegate) {
77 DCHECK(delegate);
78 delegate_ = delegate;
79
80 std::unique_ptr<ui::NativeDisplayDelegate> native_display_delegate =
81 ui::OzonePlatform::GetInstance()->CreateNativeDisplayDelegate();
82
83 // The FakeDisplayController gives us a way to make the NativeDisplayDelegate
84 // pretend something display related has happened.
85 if (!base::SysInfo::IsRunningOnChromeOS()) {
86 fake_display_controller_ =
87 native_display_delegate->GetFakeDisplayController();
88 }
89
90 // We want display configuration to happen even off device to keep the control
91 // flow similar.
92 display_configurator_.set_configure_display(true);
93 display_configurator_.AddObserver(this);
94 display_configurator_.set_state_controller(this);
95 display_configurator_.Init(std::move(native_display_delegate), false);
96 display_configurator_.ForceInitialConfigure(kChromeOsBootColor);
97 }
98
99 void PlatformScreenOzone::RequestCloseDisplay(int64_t display_id) {
100 if (!fake_display_controller_ || wait_for_display_config_update_)
101 return;
102
103 CachedDisplayIterator iter = GetCachedDisplayIterator(display_id);
104 if (iter != cached_displays_.end()) {
105 // Tell the NDD to remove the display. PlatformScreen will get an update
106 // that the display configuration has changed and the display will be gone.
107 wait_for_display_config_update_ =
108 fake_display_controller_->RemoveDisplay(iter->id);
109 }
110 }
111
112 int64_t PlatformScreenOzone::GetPrimaryDisplayId() const {
113 return primary_display_id_;
114 }
115
116 void PlatformScreenOzone::ToggleAddRemoveDisplay() {
117 if (!fake_display_controller_ || wait_for_display_config_update_)
118 return;
119
120 if (cached_displays_.size() == 1) {
121 const gfx::Size& pixel_size = cached_displays_[0].metrics.pixel_size;
122 wait_for_display_config_update_ =
123 fake_display_controller_->AddDisplay(pixel_size) != kInvalidDisplayId;
124 } else if (cached_displays_.size() > 1) {
125 wait_for_display_config_update_ =
126 fake_display_controller_->RemoveDisplay(cached_displays_.back().id);
127 } else {
128 NOTREACHED();
129 }
130 }
131
132 void PlatformScreenOzone::ToggleDisplayResolution() {
133 DisplayInfo& display = cached_displays_[0];
134
135 // Toggle the display size to use.
136 size_t num_sizes = display.supported_sizes.size();
137 for (size_t i = 0; i < num_sizes; i++) {
138 if (display.supported_sizes[i] == display.requested_size) {
139 if (i + 1 == num_sizes)
140 display.requested_size = display.supported_sizes[0];
141 else
142 display.requested_size = display.supported_sizes[i + 1];
143 break;
144 }
145 }
146
147 display_configurator_.OnConfigurationChanged();
148 }
149
150 void PlatformScreenOzone::SwapPrimaryDisplay() {
151 const size_t num_displays = cached_displays_.size();
152 if (num_displays <= 1)
153 return;
154
155 // Find index of current primary display.
156 size_t primary_display_index = 0;
157 for (size_t i = 0; i < num_displays; i++) {
158 if (cached_displays_[i].id == primary_display_id_) {
159 primary_display_index = i;
160 break;
161 }
162 }
163
164 // Set next display index as primary, or loop back to first display if last.
165 if (primary_display_index + 1 == num_displays) {
166 primary_display_id_ = cached_displays_[0].id;
167 } else {
168 primary_display_id_ = cached_displays_[primary_display_index + 1].id;
169 }
170
171 delegate_->OnPrimaryDisplayChanged(primary_display_id_);
172 }
173
174 void PlatformScreenOzone::SetDisplayWorkArea(int64_t display_id,
175 const gfx::Size& size,
176 const gfx::Insets& insets) {
177 CachedDisplayIterator iter = GetCachedDisplayIterator(display_id);
178 if (iter == cached_displays_.end()) {
179 NOTREACHED() << display_id;
180 return;
181 }
182
183 DisplayInfo& display_info = *iter;
184 if (display_info.metrics.bounds.size() == size) {
185 gfx::Rect new_work_area = display_info.metrics.bounds;
186 new_work_area.Inset(insets);
187
188 if (new_work_area != display_info.metrics.work_area) {
189 display_info.last_work_area_insets = insets;
190 display_info.metrics.work_area = new_work_area;
191 display_info.modified = true;
192 UpdateCachedDisplays();
193 }
194 }
195 }
196
197 PlatformScreenOzone::DisplayInfo::DisplayInfo() = default;
198 PlatformScreenOzone::DisplayInfo::DisplayInfo(const DisplayInfo& other) =
199 default;
200 PlatformScreenOzone::DisplayInfo::~DisplayInfo() = default;
201
202 void PlatformScreenOzone::ProcessRemovedDisplays(
203 const ui::DisplayConfigurator::DisplayStateList& snapshots) {
204 std::vector<int64_t> current_ids;
205 for (ui::DisplaySnapshot* snapshot : snapshots)
206 current_ids.push_back(snapshot->display_id());
207
208 // Find cached displays with no matching snapshot and mark as removed.
209 for (DisplayInfo& display : cached_displays_) {
210 if (std::find(current_ids.begin(), current_ids.end(), display.id) ==
211 current_ids.end()) {
212 display.removed = true;
213 if (primary_display_id_ == display.id)
214 primary_display_id_ = kInvalidDisplayId;
215 }
216 }
217 }
218
219 void PlatformScreenOzone::ProcessModifiedDisplays(
220 const ui::DisplayConfigurator::DisplayStateList& snapshots) {
221 for (ui::DisplaySnapshot* snapshot : snapshots) {
222 auto iter = GetCachedDisplayIterator(snapshot->display_id());
223 if (iter != cached_displays_.end()) {
224 DisplayInfo& display_info = *iter;
225 ViewportMetrics new_metrics =
226 MetricsFromSnapshot(*snapshot, display_info.metrics.bounds.origin());
227 new_metrics.work_area.Inset(display_info.last_work_area_insets);
228
229 if (new_metrics != display_info.metrics) {
230 display_info.metrics = new_metrics;
231 display_info.modified = true;
232 }
233 }
234 }
235 }
236
237 void PlatformScreenOzone::UpdateCachedDisplays() {
238 // Walk through cached displays after processing the snapshots to find any
239 // removed or modified displays. This ensures that we only send one update per
240 // display to the delegate.
241 next_display_origin_.SetPoint(0, 0);
242 for (auto iter = cached_displays_.begin(); iter != cached_displays_.end();) {
243 DisplayInfo& display_info = *iter;
244 if (display_info.removed) {
245 // Update delegate and remove from cache.
246 delegate_->OnDisplayRemoved(display_info.id);
247 iter = cached_displays_.erase(iter);
248 } else {
249 // Check if the display origin needs to be updated.
250 if (next_display_origin_ != display_info.metrics.bounds.origin()) {
251 display_info.metrics.bounds.set_origin(next_display_origin_);
252 display_info.metrics.work_area.set_origin(next_display_origin_);
253 display_info.modified = true;
254 }
255 next_display_origin_.Offset(display_info.metrics.bounds.width(), 0);
256
257 // Check if the window bounds have changed and update delegate.
258 if (display_info.modified) {
259 display_info.modified = false;
260 delegate_->OnDisplayModified(display_info.id, display_info.metrics);
261 }
262 ++iter;
263 }
264 }
265 }
266
267 void PlatformScreenOzone::AddNewDisplays(
268 const ui::DisplayConfigurator::DisplayStateList& snapshots) {
269 for (ui::DisplaySnapshot* snapshot : snapshots) {
270 const int64_t id = snapshot->display_id();
271
272 // Check if display already exists and skip.
273 if (GetCachedDisplayIterator(id) != cached_displays_.end())
274 continue;
275
276 DisplayInfo display_info;
277 display_info.id = snapshot->display_id();
278 display_info.metrics = MetricsFromSnapshot(*snapshot, next_display_origin_);
279
280 // Store the display mode sizes so we can toggle through them.
281 for (auto& mode : snapshot->modes()) {
282 display_info.supported_sizes.push_back(mode->size());
283 if (mode.get() == snapshot->current_mode())
284 display_info.requested_size = mode->size();
285 }
286
287 // Move the origin so that next display is to the right of current display.
288 next_display_origin_.Offset(display_info.metrics.bounds.width(), 0);
289
290 cached_displays_.push_back(display_info);
291 delegate_->OnDisplayAdded(display_info.id, display_info.metrics);
292
293 // If we have no primary display then this one should be it.
294 if (primary_display_id_ == kInvalidDisplayId) {
295 primary_display_id_ = id;
296 delegate_->OnPrimaryDisplayChanged(primary_display_id_);
297 }
298 }
299 }
300
301 PlatformScreenOzone::CachedDisplayIterator
302 PlatformScreenOzone::GetCachedDisplayIterator(int64_t display_id) {
303 return std::find_if(cached_displays_.begin(), cached_displays_.end(),
304 [display_id](const DisplayInfo& display_info) {
305 return display_info.id == display_id;
306 });
307 }
308
309 ViewportMetrics PlatformScreenOzone::MetricsFromSnapshot(
310 const ui::DisplaySnapshot& snapshot,
311 const gfx::Point& origin) {
312 const ui::DisplayMode* current_mode = snapshot.current_mode();
313 DCHECK(current_mode);
314
315 ViewportMetrics metrics;
316 metrics.pixel_size = current_mode->size();
317 metrics.device_scale_factor = FindDeviceScaleFactor(
318 ComputeDisplayDPI(current_mode->size(), snapshot.physical_size()));
319 // Get DIP size based on device scale factor. We are assuming the
320 // ui scale factor is always 1.0 here for now.
321 gfx::Size scaled_size = gfx::ScaleToRoundedSize(
322 current_mode->size(), 1.0f / metrics.device_scale_factor);
323 metrics.bounds = gfx::Rect(origin, scaled_size);
324 metrics.work_area = metrics.bounds;
325 return metrics;
326 }
327
328 void PlatformScreenOzone::OnDisplayModeChanged(
329 const ui::DisplayConfigurator::DisplayStateList& displays) {
330 ProcessRemovedDisplays(displays);
331 ProcessModifiedDisplays(displays);
332
333 // If the primary display is marked as removed we'll try to find a new primary
334 // display and update the delegate before removing the old primary display.
335 if (primary_display_id_ == kInvalidDisplayId) {
336 for (const DisplayInfo& display : cached_displays_) {
337 if (!display.removed) {
338 primary_display_id_ = display.id;
339 delegate_->OnPrimaryDisplayChanged(primary_display_id_);
340 break;
341 }
342 }
343 }
344
345 UpdateCachedDisplays();
346 AddNewDisplays(displays);
347
348 wait_for_display_config_update_ = false;
349 }
350
351 void PlatformScreenOzone::OnDisplayModeChangeFailed(
352 const ui::DisplayConfigurator::DisplayStateList& displays,
353 ui::MultipleDisplayState failed_new_state) {
354 LOG(ERROR) << "OnDisplayModeChangeFailed from DisplayConfigurator";
355 wait_for_display_config_update_ = false;
356 }
357
358 void PlatformScreenOzone::Create(
359 const service_manager::Identity& remote_identity,
360 mojom::DisplayControllerRequest request) {
361 controller_bindings_.AddBinding(this, std::move(request));
362 }
363
364 ui::MultipleDisplayState PlatformScreenOzone::GetStateForDisplayIds(
365 const ui::DisplayConfigurator::DisplayStateList& display_states) const {
366 return (display_states.size() == 1
367 ? ui::MULTIPLE_DISPLAY_STATE_SINGLE
368 : ui::MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
369 }
370
371 bool PlatformScreenOzone::GetResolutionForDisplayId(int64_t display_id,
372 gfx::Size* size) const {
373 for (const DisplayInfo& display : cached_displays_) {
374 if (display.id == display_id) {
375 *size = display.requested_size;
376 return true;
377 }
378 }
379
380 return false;
381 }
382
383 void PlatformScreenOzone::Create(
384 const service_manager::Identity& remote_identity,
385 mojom::TestDisplayControllerRequest request) {
386 test_bindings_.AddBinding(this, std::move(request));
387 }
388
389 } // namespace display
OLDNEW
« no previous file with comments | « services/ui/display/platform_screen_ozone.h ('k') | services/ui/display/platform_screen_ozone_unittests.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698