Add 'did_proceed' and 'repeat_visit' to ClientMalwareReportRequest to track CTR.
[chromium-blink-merge.git] / components / mus / display_manager.cc
blobea7d434fd2c94da55e87759d7b14d6fdf3d8b8e8
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 "components/mus/display_manager.h"
7 #include "base/numerics/safe_conversions.h"
8 #include "cc/output/compositor_frame.h"
9 #include "cc/output/delegated_frame_data.h"
10 #include "cc/quads/render_pass.h"
11 #include "cc/quads/shared_quad_state.h"
12 #include "cc/quads/surface_draw_quad.h"
13 #include "components/mus/display_manager_factory.h"
14 #include "components/mus/gles2/gpu_state.h"
15 #include "components/mus/public/interfaces/gpu.mojom.h"
16 #include "components/mus/public/interfaces/quads.mojom.h"
17 #include "components/mus/server_view.h"
18 #include "components/mus/surfaces/surfaces_state.h"
19 #include "components/mus/view_coordinate_conversions.h"
20 #include "mojo/application/public/cpp/application_connection.h"
21 #include "mojo/application/public/cpp/application_impl.h"
22 #include "mojo/converters/geometry/geometry_type_converters.h"
23 #include "mojo/converters/input_events/input_events_type_converters.h"
24 #include "mojo/converters/input_events/mojo_extended_key_event_data.h"
25 #include "mojo/converters/surfaces/surfaces_type_converters.h"
26 #include "mojo/converters/surfaces/surfaces_utils.h"
27 #include "mojo/converters/transform/transform_type_converters.h"
28 #include "third_party/skia/include/core/SkXfermode.h"
29 #include "ui/events/event.h"
30 #include "ui/events/event_utils.h"
31 #include "ui/gfx/display.h"
32 #include "ui/platform_window/platform_ime_controller.h"
33 #include "ui/platform_window/platform_window.h"
34 #include "ui/platform_window/stub/stub_window.h"
36 #if defined(OS_WIN)
37 #include "ui/platform_window/win/win_window.h"
38 #elif defined(USE_X11)
39 #include "ui/platform_window/x11/x11_window.h"
40 #elif defined(OS_ANDROID)
41 #include "ui/platform_window/android/platform_window_android.h"
42 #endif
44 using mojo::Rect;
45 using mojo::Size;
47 namespace mus {
48 namespace {
50 // DrawViewTree recursively visits ServerViews, creating a SurfaceDrawQuad for
51 // each that lacks one. For Views that already have CompositorFrames, we can
52 // skip this step and let cc::SurfaceAggregator do the heavy lifting.
53 // |skip_view| indicates whether or not we should generate a SurfaceDrawQuad
54 // for the provided |view|.
55 void DrawViewTree(cc::RenderPass* pass,
56 const ServerView* view,
57 const gfx::Vector2d& parent_to_root_origin_offset,
58 float opacity,
59 bool skip_view) {
60 if (!view->visible())
61 return;
63 const gfx::Rect absolute_bounds =
64 view->bounds() + parent_to_root_origin_offset;
66 std::vector<const ServerView*> children(view->GetChildren());
67 // TODO(rjkroege, fsamuel): Make sure we're handling alpha correctly.
68 const float combined_opacity = opacity * view->opacity();
69 for (auto it = children.rbegin(); it != children.rend(); ++it) {
70 DrawViewTree(pass, *it, absolute_bounds.OffsetFromOrigin(),
71 combined_opacity,
72 view->parent() &&
73 !view->surface_id().is_null() /* skip_view */);
76 if (skip_view || view->surface_id().is_null())
77 return;
79 gfx::Transform quad_to_target_transform;
80 quad_to_target_transform.Translate(absolute_bounds.x(), absolute_bounds.y());
81 gfx::Rect bounds_at_origin(view->bounds().size());
83 cc::SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
84 // TODO(fsamuel): These clipping and visible rects are incorrect. They need
85 // to be populated from CompositorFrame structs.
86 sqs->SetAll(
87 quad_to_target_transform, bounds_at_origin.size() /* layer_bounds */,
88 bounds_at_origin /* visible_layer_bounds */,
89 bounds_at_origin /* clip_rect */, false /* is_clipped */, view->opacity(),
90 SkXfermode::kSrc_Mode, 0 /* sorting-context_id */);
92 auto surface_quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>();
93 surface_quad->SetNew(sqs, bounds_at_origin /* rect */,
94 bounds_at_origin /* visible_rect */, view->surface_id());
97 } // namespace
99 // static
100 DisplayManagerFactory* DisplayManager::factory_ = nullptr;
102 // static
103 DisplayManager* DisplayManager::Create(
104 bool is_headless,
105 mojo::ApplicationImpl* app_impl,
106 const scoped_refptr<GpuState>& gpu_state,
107 const scoped_refptr<SurfacesState>& surfaces_state) {
108 if (factory_) {
109 return factory_->CreateDisplayManager(is_headless, app_impl, gpu_state,
110 surfaces_state);
112 return new DefaultDisplayManager(is_headless, app_impl, gpu_state,
113 surfaces_state);
116 DefaultDisplayManager::DefaultDisplayManager(
117 bool is_headless,
118 mojo::ApplicationImpl* app_impl,
119 const scoped_refptr<GpuState>& gpu_state,
120 const scoped_refptr<SurfacesState>& surfaces_state)
121 : is_headless_(is_headless),
122 app_impl_(app_impl),
123 gpu_state_(gpu_state),
124 surfaces_state_(surfaces_state),
125 delegate_(nullptr),
126 draw_timer_(false, false),
127 frame_pending_(false),
128 weak_factory_(this) {
129 metrics_.size_in_pixels = mojo::Size::New();
130 metrics_.size_in_pixels->width = 800;
131 metrics_.size_in_pixels->height = 600;
134 void DefaultDisplayManager::Init(DisplayManagerDelegate* delegate) {
135 delegate_ = delegate;
137 gfx::Rect bounds(metrics_.size_in_pixels.To<gfx::Size>());
138 if (is_headless_) {
139 platform_window_.reset(new ui::StubWindow(this));
140 } else {
141 #if defined(OS_WIN)
142 platform_window_.reset(new ui::WinWindow(this, bounds));
143 #elif defined(USE_X11)
144 platform_window_.reset(new ui::X11Window(this));
145 #elif defined(OS_ANDROID)
146 platform_window_.reset(new ui::PlatformWindowAndroid(this));
147 #else
148 NOTREACHED() << "Unsupported platform";
149 #endif
151 platform_window_->SetBounds(bounds);
152 platform_window_->Show();
155 DefaultDisplayManager::~DefaultDisplayManager() {
156 // Invalidate WeakPtrs now to avoid callbacks back into the
157 // DefaultDisplayManager during destruction of |top_level_display_client_|.
158 weak_factory_.InvalidateWeakPtrs();
159 top_level_display_client_.reset();
160 // Destroy the PlatformWindow early on as it may call us back during
161 // destruction and we want to be in a known state. But destroy the surface
162 // first because it can still be using the platform window.
163 platform_window_.reset();
166 void DefaultDisplayManager::SchedulePaint(const ServerView* view,
167 const gfx::Rect& bounds) {
168 DCHECK(view);
169 if (!view->IsDrawn())
170 return;
171 const gfx::Rect root_relative_rect =
172 ConvertRectBetweenViews(view, delegate_->GetRootView(), bounds);
173 if (root_relative_rect.IsEmpty())
174 return;
175 dirty_rect_.Union(root_relative_rect);
176 WantToDraw();
179 void DefaultDisplayManager::SetViewportSize(const gfx::Size& size) {
180 platform_window_->SetBounds(gfx::Rect(size));
183 void DefaultDisplayManager::SetTitle(const base::string16& title) {
184 platform_window_->SetTitle(title);
187 const mojo::ViewportMetrics& DefaultDisplayManager::GetViewportMetrics() {
188 return metrics_;
191 void DefaultDisplayManager::UpdateTextInputState(
192 const ui::TextInputState& state) {
193 ui::PlatformImeController* ime = platform_window_->GetPlatformImeController();
194 if (ime)
195 ime->UpdateTextInputState(state);
198 void DefaultDisplayManager::SetImeVisibility(bool visible) {
199 ui::PlatformImeController* ime = platform_window_->GetPlatformImeController();
200 if (ime)
201 ime->SetImeVisibility(visible);
204 void DefaultDisplayManager::Draw() {
205 if (!delegate_->GetRootView()->visible())
206 return;
208 // TODO(fsamuel): We should add a trace for generating a top level frame.
209 scoped_ptr<cc::CompositorFrame> frame(GenerateCompositorFrame());
210 frame_pending_ = true;
211 if (top_level_display_client_) {
212 top_level_display_client_->SubmitCompositorFrame(
213 frame.Pass(), base::Bind(&DefaultDisplayManager::DidDraw,
214 weak_factory_.GetWeakPtr()));
216 dirty_rect_ = gfx::Rect();
219 void DefaultDisplayManager::DidDraw() {
220 frame_pending_ = false;
221 if (!dirty_rect_.IsEmpty())
222 WantToDraw();
225 void DefaultDisplayManager::WantToDraw() {
226 if (draw_timer_.IsRunning() || frame_pending_)
227 return;
229 draw_timer_.Start(
230 FROM_HERE, base::TimeDelta(),
231 base::Bind(&DefaultDisplayManager::Draw, weak_factory_.GetWeakPtr()));
234 void DefaultDisplayManager::UpdateMetrics(const gfx::Size& size,
235 float device_pixel_ratio) {
236 if (gfx::Display::HasForceDeviceScaleFactor())
237 device_pixel_ratio = gfx::Display::GetForcedDeviceScaleFactor();
238 if (metrics_.size_in_pixels.To<gfx::Size>() == size &&
239 metrics_.device_pixel_ratio == device_pixel_ratio)
240 return;
241 mojo::ViewportMetrics old_metrics;
242 old_metrics.size_in_pixels = metrics_.size_in_pixels.Clone();
243 old_metrics.device_pixel_ratio = metrics_.device_pixel_ratio;
245 metrics_.size_in_pixels = mojo::Size::From(size);
246 metrics_.device_pixel_ratio = device_pixel_ratio;
248 delegate_->OnViewportMetricsChanged(old_metrics, metrics_);
251 scoped_ptr<cc::CompositorFrame>
252 DefaultDisplayManager::GenerateCompositorFrame() {
253 scoped_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create();
254 render_pass->damage_rect = dirty_rect_;
255 render_pass->output_rect = gfx::Rect(metrics_.size_in_pixels.To<gfx::Size>());
257 DrawViewTree(render_pass.get(),
258 delegate_->GetRootView(),
259 gfx::Vector2d(), 1.0f,
260 false /* skip_view */);
262 scoped_ptr<cc::DelegatedFrameData> frame_data(new cc::DelegatedFrameData);
263 frame_data->device_scale_factor = metrics_.device_pixel_ratio;
264 frame_data->render_pass_list.push_back(render_pass.Pass());
266 scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
267 frame->delegated_frame_data = frame_data.Pass();
268 return frame.Pass();
271 const cc::CompositorFrame*
272 DefaultDisplayManager::GetLastCompositorFrame() const {
273 if (!top_level_display_client_)
274 return nullptr;
276 return top_level_display_client_->GetLastCompositorFrame();
279 void DefaultDisplayManager::OnBoundsChanged(const gfx::Rect& new_bounds) {
280 UpdateMetrics(new_bounds.size(), metrics_.device_pixel_ratio);
283 void DefaultDisplayManager::OnDamageRect(const gfx::Rect& damaged_region) {
284 dirty_rect_.Union(damaged_region);
285 WantToDraw();
288 void DefaultDisplayManager::DispatchEvent(ui::Event* event) {
289 mojo::EventPtr mojo_event(mojo::Event::From(*event));
290 ViewId id;
291 if (event->IsLocatedEvent() && !!top_level_display_client_) {
292 ui::LocatedEvent* located_event = static_cast<ui::LocatedEvent*>(event);
293 gfx::Point transformed_point;
294 cc::SurfaceId target_surface =
295 surfaces_state_->hit_tester()->GetTargetSurfaceAtPoint(
296 top_level_display_client_->surface_id(),
297 located_event->location(),
298 &transformed_point);
299 id = ViewIdFromTransportId(
300 cc::SurfaceIdAllocator::NamespaceForId(target_surface));
302 mojo::LocationData* location = nullptr;
303 if (mojo_event->pointer_data)
304 location = mojo_event->pointer_data->location.get();
305 else if (mojo_event->wheel_data)
306 location = mojo_event->wheel_data->location.get();
308 DCHECK(location);
309 location->x = transformed_point.x();
310 location->y = transformed_point.y();
312 delegate_->OnEvent(id, mojo_event.Pass());
314 switch (event->type()) {
315 case ui::ET_MOUSE_PRESSED:
316 case ui::ET_TOUCH_PRESSED:
317 platform_window_->SetCapture();
318 break;
319 case ui::ET_MOUSE_RELEASED:
320 case ui::ET_TOUCH_RELEASED:
321 platform_window_->ReleaseCapture();
322 break;
323 default:
324 break;
327 #if defined(USE_X11)
328 // We want to emulate the WM_CHAR generation behaviour of Windows.
330 // On Linux, we've previously inserted characters by having
331 // InputMethodAuraLinux take all key down events and send a character event
332 // to the TextInputClient. This causes a mismatch in code that has to be
333 // shared between Windows and Linux, including blink code. Now that we're
334 // trying to have one way of doing things, we need to standardize on and
335 // emulate Windows character events.
337 // This is equivalent to what we're doing in the current Linux port, but
338 // done once instead of done multiple times in different places.
339 if (event->type() == ui::ET_KEY_PRESSED) {
340 ui::KeyEvent* key_press_event = static_cast<ui::KeyEvent*>(event);
341 ui::KeyEvent char_event(key_press_event->GetCharacter(),
342 key_press_event->key_code(),
343 key_press_event->flags());
345 DCHECK_EQ(key_press_event->GetCharacter(), char_event.GetCharacter());
346 DCHECK_EQ(key_press_event->key_code(), char_event.key_code());
347 DCHECK_EQ(key_press_event->flags(), char_event.flags());
349 char_event.SetExtendedKeyEventData(
350 make_scoped_ptr(new mojo::MojoExtendedKeyEventData(
351 key_press_event->GetLocatedWindowsKeyboardCode(),
352 key_press_event->GetText(), key_press_event->GetUnmodifiedText())));
354 delegate_->OnEvent(id, mojo::Event::From(char_event));
356 #endif
359 void DefaultDisplayManager::OnCloseRequest() {
360 platform_window_->Close();
363 void DefaultDisplayManager::OnClosed() {
364 delegate_->OnDisplayClosed();
367 void DefaultDisplayManager::OnWindowStateChanged(
368 ui::PlatformWindowState new_state) {}
370 void DefaultDisplayManager::OnLostCapture() {}
372 void DefaultDisplayManager::OnAcceleratedWidgetAvailable(
373 gfx::AcceleratedWidget widget,
374 float device_pixel_ratio) {
375 if (widget != gfx::kNullAcceleratedWidget) {
376 top_level_display_client_.reset(
377 new TopLevelDisplayClient(widget, gpu_state_, surfaces_state_));
379 UpdateMetrics(metrics_.size_in_pixels.To<gfx::Size>(), device_pixel_ratio);
382 void DefaultDisplayManager::OnActivationChanged(bool active) {}
384 } // namespace mus