Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / browser / renderer_host / render_widget_host_view_android.cc
blobef6a2893198e5ed30c9862e656107f99b1498aa4
1 // Copyright (c) 2012 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 "content/browser/renderer_host/render_widget_host_view_android.h"
7 #include <android/bitmap.h>
9 #include "base/android/build_info.h"
10 #include "base/basictypes.h"
11 #include "base/bind.h"
12 #include "base/callback_helpers.h"
13 #include "base/command_line.h"
14 #include "base/logging.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/metrics/histogram.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/sys_info.h"
19 #include "base/threading/worker_pool.h"
20 #include "cc/layers/delegated_frame_provider.h"
21 #include "cc/layers/delegated_renderer_layer.h"
22 #include "cc/layers/layer.h"
23 #include "cc/layers/surface_layer.h"
24 #include "cc/output/compositor_frame.h"
25 #include "cc/output/compositor_frame_ack.h"
26 #include "cc/output/copy_output_request.h"
27 #include "cc/output/copy_output_result.h"
28 #include "cc/output/latency_info_swap_promise.h"
29 #include "cc/output/viewport_selection_bound.h"
30 #include "cc/resources/single_release_callback.h"
31 #include "cc/surfaces/surface.h"
32 #include "cc/surfaces/surface_factory.h"
33 #include "cc/surfaces/surface_id_allocator.h"
34 #include "cc/surfaces/surface_manager.h"
35 #include "cc/trees/layer_tree_host.h"
36 #include "content/browser/accessibility/browser_accessibility_manager_android.h"
37 #include "content/browser/android/composited_touch_handle_drawable.h"
38 #include "content/browser/android/content_view_core_impl.h"
39 #include "content/browser/android/edge_effect.h"
40 #include "content/browser/android/edge_effect_l.h"
41 #include "content/browser/android/in_process/synchronous_compositor_impl.h"
42 #include "content/browser/android/overscroll_controller_android.h"
43 #include "content/browser/android/popup_touch_handle_drawable.h"
44 #include "content/browser/devtools/render_frame_devtools_agent_host.h"
45 #include "content/browser/gpu/browser_gpu_channel_host_factory.h"
46 #include "content/browser/gpu/compositor_util.h"
47 #include "content/browser/gpu/gpu_data_manager_impl.h"
48 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
49 #include "content/browser/gpu/gpu_surface_tracker.h"
50 #include "content/browser/media/media_web_contents_observer.h"
51 #include "content/browser/renderer_host/compositor_impl_android.h"
52 #include "content/browser/renderer_host/dip_util.h"
53 #include "content/browser/renderer_host/frame_metadata_util.h"
54 #include "content/browser/renderer_host/input/synthetic_gesture_target_android.h"
55 #include "content/browser/renderer_host/input/ui_touch_selection_helper.h"
56 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
57 #include "content/browser/renderer_host/input/web_input_event_util.h"
58 #include "content/browser/renderer_host/render_process_host_impl.h"
59 #include "content/browser/renderer_host/render_view_host_impl.h"
60 #include "content/browser/renderer_host/render_widget_host_impl.h"
61 #include "content/common/gpu/client/gl_helper.h"
62 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
63 #include "content/common/gpu/gpu_messages.h"
64 #include "content/common/gpu/gpu_process_launch_causes.h"
65 #include "content/common/input/did_overscroll_params.h"
66 #include "content/common/input_messages.h"
67 #include "content/common/view_messages.h"
68 #include "content/public/browser/android/compositor.h"
69 #include "content/public/browser/browser_thread.h"
70 #include "content/public/browser/devtools_agent_host.h"
71 #include "content/public/browser/render_view_host.h"
72 #include "content/public/browser/render_widget_host_iterator.h"
73 #include "content/public/common/content_switches.h"
74 #include "gpu/command_buffer/client/gles2_implementation.h"
75 #include "gpu/command_buffer/client/gles2_interface.h"
76 #include "gpu/config/gpu_driver_bug_workaround_type.h"
77 #include "skia/ext/image_operations.h"
78 #include "third_party/khronos/GLES2/gl2.h"
79 #include "third_party/khronos/GLES2/gl2ext.h"
80 #include "third_party/skia/include/core/SkCanvas.h"
81 #include "ui/android/window_android.h"
82 #include "ui/android/window_android_compositor.h"
83 #include "ui/events/blink/blink_event_util.h"
84 #include "ui/events/gesture_detection/gesture_provider_config_helper.h"
85 #include "ui/events/gesture_detection/motion_event.h"
86 #include "ui/gfx/android/device_display_info.h"
87 #include "ui/gfx/android/java_bitmap.h"
88 #include "ui/gfx/android/view_configuration.h"
89 #include "ui/gfx/display.h"
90 #include "ui/gfx/geometry/dip_util.h"
91 #include "ui/gfx/geometry/size_conversions.h"
92 #include "ui/gfx/screen.h"
93 #include "ui/touch_selection/touch_selection_controller.h"
95 namespace content {
97 namespace {
99 void SatisfyCallback(cc::SurfaceManager* manager,
100 cc::SurfaceSequence sequence) {
101 std::vector<uint32_t> sequences;
102 sequences.push_back(sequence.sequence);
103 manager->DidSatisfySequences(sequence.id_namespace, &sequences);
106 void RequireCallback(cc::SurfaceManager* manager,
107 cc::SurfaceId id,
108 cc::SurfaceSequence sequence) {
109 cc::Surface* surface = manager->GetSurfaceForId(id);
110 if (!surface) {
111 LOG(ERROR) << "Attempting to require callback on nonexistent surface";
112 return;
114 surface->AddDestructionDependency(sequence);
117 const int kUndefinedOutputSurfaceId = -1;
119 static const char kAsyncReadBackString[] = "Compositing.CopyFromSurfaceTime";
121 class GLHelperHolder
122 : public blink::WebGraphicsContext3D::WebGraphicsContextLostCallback {
123 public:
124 static GLHelperHolder* Create();
125 ~GLHelperHolder() override;
127 void Initialize();
129 // WebGraphicsContextLostCallback implementation.
130 void onContextLost() override;
132 GLHelper* GetGLHelper() { return gl_helper_.get(); }
133 bool IsLost() { return !context_.get() || context_->isContextLost(); }
135 private:
136 GLHelperHolder();
137 static scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateContext3D();
139 scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context_;
140 scoped_ptr<GLHelper> gl_helper_;
142 DISALLOW_COPY_AND_ASSIGN(GLHelperHolder);
145 GLHelperHolder* GLHelperHolder::Create() {
146 GLHelperHolder* holder = new GLHelperHolder;
147 holder->Initialize();
149 return holder;
152 GLHelperHolder::GLHelperHolder() {
155 GLHelperHolder::~GLHelperHolder() {
158 void GLHelperHolder::Initialize() {
159 context_ = CreateContext3D();
160 if (context_) {
161 context_->setContextLostCallback(this);
162 gl_helper_.reset(new GLHelper(context_->GetImplementation(),
163 context_->GetContextSupport()));
167 void GLHelperHolder::onContextLost() {
168 // Need to post a task because the command buffer client cannot be deleted
169 // from within this callback.
170 LOG(ERROR) << "Context lost.";
171 base::MessageLoop::current()->PostTask(
172 FROM_HERE,
173 base::Bind(&RenderWidgetHostViewAndroid::OnContextLost));
176 scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
177 GLHelperHolder::CreateContext3D() {
178 BrowserGpuChannelHostFactory* factory =
179 BrowserGpuChannelHostFactory::instance();
180 scoped_refptr<GpuChannelHost> gpu_channel_host(factory->GetGpuChannel());
181 // GLHelper can only be used in asynchronous APIs for postprocessing after
182 // Browser Compositor operations (i.e. readback).
183 if (!gpu_channel_host.get()) {
184 // The Browser Compositor is in charge of reestablishing the channel.
185 return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
188 blink::WebGraphicsContext3D::Attributes attrs;
189 attrs.shareResources = true;
190 GURL url("chrome://gpu/RenderWidgetHostViewAndroid");
191 static const size_t kBytesPerPixel = 4;
192 gfx::DeviceDisplayInfo display_info;
193 size_t full_screen_texture_size_in_bytes = display_info.GetDisplayHeight() *
194 display_info.GetDisplayWidth() *
195 kBytesPerPixel;
196 WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits;
197 limits.command_buffer_size = 64 * 1024;
198 limits.start_transfer_buffer_size = 64 * 1024;
199 limits.min_transfer_buffer_size = 64 * 1024;
200 limits.max_transfer_buffer_size = std::min(
201 3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize);
202 limits.mapped_memory_reclaim_limit =
203 WebGraphicsContext3DCommandBufferImpl::kNoLimit;
204 bool lose_context_when_out_of_memory = false;
205 scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
206 new WebGraphicsContext3DCommandBufferImpl(
207 0, // offscreen
208 url, gpu_channel_host.get(), attrs, lose_context_when_out_of_memory,
209 limits, nullptr));
210 context->SetContextType(BROWSER_OFFSCREEN_MAINTHREAD_CONTEXT);
211 if (context->InitializeOnCurrentThread()) {
212 context->traceBeginCHROMIUM(
213 "gpu_toplevel",
214 base::StringPrintf("CmdBufferImageTransportFactory-%p",
215 context.get()).c_str());
216 } else {
217 context.reset();
220 return context.Pass();
223 // This can only be used for readback postprocessing. It may return null if the
224 // channel was lost and not reestablished yet.
225 GLHelper* GetPostReadbackGLHelper() {
226 static GLHelperHolder* g_readback_helper_holder = nullptr;
228 if (g_readback_helper_holder && g_readback_helper_holder->IsLost()) {
229 delete g_readback_helper_holder;
230 g_readback_helper_holder = nullptr;
233 if (!g_readback_helper_holder)
234 g_readback_helper_holder = GLHelperHolder::Create();
236 return g_readback_helper_holder->GetGLHelper();
239 void CopyFromCompositingSurfaceFinished(
240 ReadbackRequestCallback& callback,
241 scoped_ptr<cc::SingleReleaseCallback> release_callback,
242 scoped_ptr<SkBitmap> bitmap,
243 const base::TimeTicks& start_time,
244 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
245 bool result) {
246 TRACE_EVENT0(
247 "cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceFinished");
248 bitmap_pixels_lock.reset();
249 uint32 sync_point = 0;
250 if (result) {
251 GLHelper* gl_helper = GetPostReadbackGLHelper();
252 if (gl_helper)
253 sync_point = gl_helper->InsertSyncPoint();
255 bool lost_resource = sync_point == 0;
256 release_callback->Run(sync_point, lost_resource);
257 UMA_HISTOGRAM_TIMES(kAsyncReadBackString,
258 base::TimeTicks::Now() - start_time);
259 ReadbackResponse response = result ? READBACK_SUCCESS : READBACK_FAILED;
260 callback.Run(*bitmap, response);
263 scoped_ptr<ui::TouchSelectionController> CreateSelectionController(
264 ui::TouchSelectionControllerClient* client,
265 ContentViewCore* content_view_core) {
266 DCHECK(client);
267 DCHECK(content_view_core);
268 ui::TouchSelectionController::Config config;
269 config.max_tap_duration = base::TimeDelta::FromMilliseconds(
270 gfx::ViewConfiguration::GetLongPressTimeoutInMs());
271 config.tap_slop = gfx::ViewConfiguration::GetTouchSlopInDips();
272 config.show_on_tap_for_empty_editable = false;
273 config.enable_longpress_drag_selection =
274 base::CommandLine::ForCurrentProcess()->HasSwitch(
275 switches::kEnableLongpressDragSelection);
276 return make_scoped_ptr(new ui::TouchSelectionController(client, config));
279 scoped_ptr<OverscrollControllerAndroid> CreateOverscrollController(
280 ContentViewCoreImpl* content_view_core) {
281 return make_scoped_ptr(new OverscrollControllerAndroid(content_view_core));
284 gfx::RectF GetSelectionRect(const ui::TouchSelectionController& controller) {
285 gfx::RectF rect = controller.GetRectBetweenBounds();
286 if (rect.IsEmpty())
287 return rect;
289 rect.Union(controller.GetStartHandleRect());
290 rect.Union(controller.GetEndHandleRect());
291 return rect;
294 } // anonymous namespace
296 RenderWidgetHostViewAndroid::LastFrameInfo::LastFrameInfo(
297 uint32 output_id,
298 scoped_ptr<cc::CompositorFrame> output_frame)
299 : output_surface_id(output_id), frame(output_frame.Pass()) {}
301 RenderWidgetHostViewAndroid::LastFrameInfo::~LastFrameInfo() {}
303 void RenderWidgetHostViewAndroid::OnContextLost() {
304 scoped_ptr<RenderWidgetHostIterator> widgets(
305 RenderWidgetHostImpl::GetAllRenderWidgetHosts());
306 while (RenderWidgetHost* widget = widgets->GetNextHost()) {
307 if (widget->GetView()) {
308 static_cast<RenderWidgetHostViewAndroid*>(widget->GetView())
309 ->OnLostResources();
314 RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
315 RenderWidgetHostImpl* widget_host,
316 ContentViewCoreImpl* content_view_core)
317 : host_(widget_host),
318 outstanding_vsync_requests_(0),
319 is_showing_(!widget_host->is_hidden()),
320 content_view_core_(nullptr),
321 content_view_core_window_android_(nullptr),
322 ime_adapter_android_(this),
323 cached_background_color_(SK_ColorWHITE),
324 last_output_surface_id_(kUndefinedOutputSurfaceId),
325 gesture_provider_(ui::GetGestureProviderConfig(
326 ui::GestureProviderConfigType::CURRENT_PLATFORM),
327 this),
328 stylus_text_selector_(this),
329 accelerated_surface_route_id_(0),
330 using_browser_compositor_(CompositorImpl::IsInitialized()),
331 frame_evictor_(new DelegatedFrameEvictor(this)),
332 locks_on_frame_count_(0),
333 observing_root_window_(false),
334 weak_ptr_factory_(this) {
335 if (CompositorImpl::GetSurfaceManager())
336 id_allocator_ = CompositorImpl::CreateSurfaceIdAllocator();
337 host_->SetView(this);
338 SetContentViewCore(content_view_core);
341 RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() {
342 SetContentViewCore(NULL);
343 DCHECK(ack_callbacks_.empty());
344 if (resource_collection_.get())
345 resource_collection_->SetClient(NULL);
346 DCHECK(!surface_factory_);
347 DCHECK(surface_id_.is_null());
350 void RenderWidgetHostViewAndroid::Blur() {
351 host_->Blur();
352 if (overscroll_controller_)
353 overscroll_controller_->Disable();
356 bool RenderWidgetHostViewAndroid::OnMessageReceived(
357 const IPC::Message& message) {
358 bool handled = true;
359 IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAndroid, message)
360 IPC_MESSAGE_HANDLER(ViewHostMsg_StartContentIntent, OnStartContentIntent)
361 IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrames,
362 OnSetNeedsBeginFrames)
363 IPC_MESSAGE_HANDLER(ViewHostMsg_SmartClipDataExtracted,
364 OnSmartClipDataExtracted)
365 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowUnhandledTapUIIfNeeded,
366 OnShowUnhandledTapUIIfNeeded)
367 IPC_MESSAGE_UNHANDLED(handled = false)
368 IPC_END_MESSAGE_MAP()
369 return handled;
372 void RenderWidgetHostViewAndroid::InitAsChild(gfx::NativeView parent_view) {
373 NOTIMPLEMENTED();
376 void RenderWidgetHostViewAndroid::InitAsPopup(
377 RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) {
378 NOTIMPLEMENTED();
381 void RenderWidgetHostViewAndroid::InitAsFullscreen(
382 RenderWidgetHostView* reference_host_view) {
383 NOTIMPLEMENTED();
386 RenderWidgetHost*
387 RenderWidgetHostViewAndroid::GetRenderWidgetHost() const {
388 return host_;
391 void RenderWidgetHostViewAndroid::WasResized() {
392 host_->WasResized();
395 void RenderWidgetHostViewAndroid::SetSize(const gfx::Size& size) {
396 // Ignore the given size as only the Java code has the power to
397 // resize the view on Android.
398 default_size_ = size;
401 void RenderWidgetHostViewAndroid::SetBounds(const gfx::Rect& rect) {
402 SetSize(rect.size());
405 void RenderWidgetHostViewAndroid::GetScaledContentBitmap(
406 float scale,
407 SkColorType preferred_color_type,
408 gfx::Rect src_subrect,
409 ReadbackRequestCallback& result_callback) {
410 if (!host_ || host_->is_hidden() || !IsSurfaceAvailableForCopy()) {
411 result_callback.Run(SkBitmap(), READBACK_SURFACE_UNAVAILABLE);
412 return;
414 gfx::Size bounds = layer_->bounds();
415 if (src_subrect.IsEmpty())
416 src_subrect = gfx::Rect(bounds);
417 DCHECK_LE(src_subrect.width() + src_subrect.x(), bounds.width());
418 DCHECK_LE(src_subrect.height() + src_subrect.y(), bounds.height());
419 const gfx::Display& display =
420 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
421 float device_scale_factor = display.device_scale_factor();
422 DCHECK_GT(device_scale_factor, 0);
423 gfx::Size dst_size(gfx::ToCeiledSize(
424 gfx::ScaleSize(src_subrect.size(), scale / device_scale_factor)));
425 src_subrect = gfx::ConvertRectToDIP(device_scale_factor, src_subrect);
427 CopyFromCompositingSurface(src_subrect, dst_size, result_callback,
428 preferred_color_type);
431 scoped_refptr<cc::Layer> RenderWidgetHostViewAndroid::CreateDelegatedLayer()
432 const {
433 scoped_refptr<cc::Layer> delegated_layer;
434 if (!surface_id_.is_null()) {
435 cc::SurfaceManager* manager = CompositorImpl::GetSurfaceManager();
436 DCHECK(manager);
437 // manager must outlive compositors using it.
438 scoped_refptr<cc::SurfaceLayer> surface_layer = cc::SurfaceLayer::Create(
439 Compositor::LayerSettings(),
440 base::Bind(&SatisfyCallback, base::Unretained(manager)),
441 base::Bind(&RequireCallback, base::Unretained(manager)));
442 surface_layer->SetSurfaceId(surface_id_, 1.f, texture_size_in_layer_);
443 delegated_layer = surface_layer;
444 } else {
445 DCHECK(frame_provider_.get());
446 delegated_layer = cc::DelegatedRendererLayer::Create(
447 Compositor::LayerSettings(), frame_provider_);
449 delegated_layer->SetBounds(texture_size_in_layer_);
450 delegated_layer->SetIsDrawable(true);
451 delegated_layer->SetContentsOpaque(true);
453 return delegated_layer;
456 bool RenderWidgetHostViewAndroid::HasValidFrame() const {
457 if (!content_view_core_)
458 return false;
459 if (!layer_.get())
460 return false;
462 if (texture_size_in_layer_.IsEmpty())
463 return false;
464 // This tell us whether a valid frame has arrived or not.
465 if (!frame_evictor_->HasFrame())
466 return false;
468 return true;
471 gfx::Vector2dF RenderWidgetHostViewAndroid::GetLastScrollOffset() const {
472 return last_scroll_offset_;
475 gfx::NativeView RenderWidgetHostViewAndroid::GetNativeView() const {
476 return content_view_core_->GetViewAndroid();
479 gfx::NativeViewId RenderWidgetHostViewAndroid::GetNativeViewId() const {
480 return reinterpret_cast<gfx::NativeViewId>(
481 const_cast<RenderWidgetHostViewAndroid*>(this));
484 gfx::NativeViewAccessible
485 RenderWidgetHostViewAndroid::GetNativeViewAccessible() {
486 NOTIMPLEMENTED();
487 return NULL;
490 void RenderWidgetHostViewAndroid::MovePluginWindows(
491 const std::vector<WebPluginGeometry>& moves) {
492 // We don't have plugin windows on Android. Do nothing. Note: this is called
493 // from RenderWidgetHost::OnUpdateRect which is itself invoked while
494 // processing the corresponding message from Renderer.
497 void RenderWidgetHostViewAndroid::Focus() {
498 host_->Focus();
499 if (overscroll_controller_)
500 overscroll_controller_->Enable();
501 if (content_view_core_) {
502 WebContentsImpl* web_contents_impl =
503 static_cast<WebContentsImpl*>(content_view_core_->GetWebContents());
504 if (web_contents_impl->ShowingInterstitialPage())
505 content_view_core_->ForceUpdateImeAdapter(GetNativeImeAdapter());
509 bool RenderWidgetHostViewAndroid::HasFocus() const {
510 if (!content_view_core_)
511 return false; // ContentViewCore not created yet.
513 return content_view_core_->HasFocus();
516 bool RenderWidgetHostViewAndroid::IsSurfaceAvailableForCopy() const {
517 return HasValidFrame();
520 void RenderWidgetHostViewAndroid::Show() {
521 if (is_showing_)
522 return;
524 is_showing_ = true;
525 ShowInternal();
528 void RenderWidgetHostViewAndroid::Hide() {
529 if (!is_showing_)
530 return;
532 is_showing_ = false;
534 bool hide_frontbuffer = true;
535 bool stop_observing_root_window = true;
536 HideInternal(hide_frontbuffer, stop_observing_root_window);
539 bool RenderWidgetHostViewAndroid::IsShowing() {
540 // ContentViewCoreImpl represents the native side of the Java
541 // ContentViewCore. It being NULL means that it is not attached
542 // to the View system yet, so we treat this RWHVA as hidden.
543 return is_showing_ && content_view_core_;
546 void RenderWidgetHostViewAndroid::LockCompositingSurface() {
547 DCHECK(HasValidFrame());
548 DCHECK(host_);
549 DCHECK(frame_evictor_->HasFrame());
550 frame_evictor_->LockFrame();
551 locks_on_frame_count_++;
554 void RenderWidgetHostViewAndroid::UnlockCompositingSurface() {
555 if (!frame_evictor_->HasFrame() || locks_on_frame_count_ == 0)
556 return;
558 DCHECK(HasValidFrame());
559 frame_evictor_->UnlockFrame();
560 locks_on_frame_count_--;
562 if (locks_on_frame_count_ == 0) {
563 if (last_frame_info_) {
564 InternalSwapCompositorFrame(last_frame_info_->output_surface_id,
565 last_frame_info_->frame.Pass());
566 last_frame_info_.reset();
569 if (!is_showing_ && layer_.get())
570 layer_->SetHideLayerAndSubtree(true);
574 void RenderWidgetHostViewAndroid::SetTextSurroundingSelectionCallback(
575 const TextSurroundingSelectionCallback& callback) {
576 // Only one outstanding request is allowed at any given time.
577 DCHECK(!callback.is_null());
578 text_surrounding_selection_callback_ = callback;
581 void RenderWidgetHostViewAndroid::OnTextSurroundingSelectionResponse(
582 const base::string16& content,
583 size_t start_offset,
584 size_t end_offset) {
585 if (text_surrounding_selection_callback_.is_null())
586 return;
587 text_surrounding_selection_callback_.Run(content, start_offset, end_offset);
588 text_surrounding_selection_callback_.Reset();
591 void RenderWidgetHostViewAndroid::OnShowUnhandledTapUIIfNeeded(int x_dip,
592 int y_dip) {
593 if (!content_view_core_)
594 return;
595 // Validate the coordinates are within the viewport.
596 gfx::Size viewport_size = content_view_core_->GetViewportSizeDip();
597 if (x_dip < 0 || x_dip > viewport_size.width() ||
598 y_dip < 0 || y_dip > viewport_size.height())
599 return;
600 content_view_core_->OnShowUnhandledTapUIIfNeeded(x_dip, y_dip);
603 void RenderWidgetHostViewAndroid::ReleaseLocksOnSurface() {
604 if (!frame_evictor_->HasFrame()) {
605 DCHECK_EQ(locks_on_frame_count_, 0u);
606 return;
608 while (locks_on_frame_count_ > 0) {
609 UnlockCompositingSurface();
611 RunAckCallbacks(cc::SurfaceDrawStatus::DRAW_SKIPPED);
614 gfx::Rect RenderWidgetHostViewAndroid::GetViewBounds() const {
615 if (!content_view_core_)
616 return gfx::Rect(default_size_);
618 return gfx::Rect(content_view_core_->GetViewSize());
621 gfx::Size RenderWidgetHostViewAndroid::GetPhysicalBackingSize() const {
622 if (!content_view_core_)
623 return gfx::Size();
625 return content_view_core_->GetPhysicalBackingSize();
628 bool RenderWidgetHostViewAndroid::DoTopControlsShrinkBlinkSize() const {
629 if (!content_view_core_)
630 return false;
632 // Whether or not Blink's viewport size should be shrunk by the height of the
633 // URL-bar.
634 return content_view_core_->DoTopControlsShrinkBlinkSize();
637 float RenderWidgetHostViewAndroid::GetTopControlsHeight() const {
638 if (!content_view_core_)
639 return 0.f;
641 // The height of the top controls.
642 return content_view_core_->GetTopControlsHeightDip();
645 void RenderWidgetHostViewAndroid::UpdateCursor(const WebCursor& cursor) {
646 // There are no cursors on Android.
649 void RenderWidgetHostViewAndroid::SetIsLoading(bool is_loading) {
650 // Do nothing. The UI notification is handled through ContentViewClient which
651 // is TabContentsDelegate.
654 long RenderWidgetHostViewAndroid::GetNativeImeAdapter() {
655 return reinterpret_cast<intptr_t>(&ime_adapter_android_);
658 void RenderWidgetHostViewAndroid::TextInputStateChanged(
659 const ViewHostMsg_TextInputState_Params& params) {
660 if (params.is_non_ime_change) {
661 // Sends an acknowledgement to the renderer of a processed IME event.
662 host_->Send(new InputMsg_ImeEventAck(host_->GetRoutingID()));
665 if (!IsShowing())
666 return;
668 content_view_core_->UpdateImeAdapter(
669 GetNativeImeAdapter(),
670 static_cast<int>(params.type), params.flags,
671 params.value, params.selection_start, params.selection_end,
672 params.composition_start, params.composition_end,
673 params.show_ime_if_needed, params.is_non_ime_change);
676 void RenderWidgetHostViewAndroid::UpdateBackgroundColor(SkColor color) {
677 if (cached_background_color_ == color)
678 return;
680 cached_background_color_ = color;
681 if (content_view_core_)
682 content_view_core_->OnBackgroundColorChanged(color);
685 void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrames(bool enabled) {
686 TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::OnSetNeedsBeginFrames",
687 "enabled", enabled);
688 if (enabled)
689 RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME);
690 else
691 outstanding_vsync_requests_ &= ~PERSISTENT_BEGIN_FRAME;
694 void RenderWidgetHostViewAndroid::OnStartContentIntent(
695 const GURL& content_url) {
696 if (content_view_core_)
697 content_view_core_->StartContentIntent(content_url);
700 void RenderWidgetHostViewAndroid::OnSmartClipDataExtracted(
701 const base::string16& text,
702 const base::string16& html,
703 const gfx::Rect rect) {
704 if (content_view_core_)
705 content_view_core_->OnSmartClipDataExtracted(text, html, rect);
708 bool RenderWidgetHostViewAndroid::OnTouchEvent(
709 const ui::MotionEvent& event) {
710 if (!host_)
711 return false;
713 // If a browser-based widget consumes the touch event, it's critical that
714 // touch event interception be disabled. This avoids issues with
715 // double-handling for embedder-detected gestures like side swipe.
716 if (selection_controller_ &&
717 selection_controller_->WillHandleTouchEvent(event)) {
718 RequestDisallowInterceptTouchEvent();
719 return true;
722 if (stylus_text_selector_.OnTouchEvent(event)) {
723 RequestDisallowInterceptTouchEvent();
724 return true;
727 ui::FilteredGestureProvider::TouchHandlingResult result =
728 gesture_provider_.OnTouchEvent(event);
729 if (!result.succeeded)
730 return false;
732 blink::WebTouchEvent web_event =
733 ui::CreateWebTouchEventFromMotionEvent(event, result.did_generate_scroll);
734 host_->ForwardTouchEventWithLatencyInfo(web_event, ui::LatencyInfo());
736 // Send a proactive BeginFrame for this vsync to reduce scroll latency for
737 // scroll-inducing touch events. Note that Android's Choreographer ensures
738 // that BeginFrame requests made during ACTION_MOVE dispatch will be honored
739 // in the same vsync phase.
740 if (observing_root_window_&& result.did_generate_scroll)
741 RequestVSyncUpdate(BEGIN_FRAME);
743 return true;
746 bool RenderWidgetHostViewAndroid::OnTouchHandleEvent(
747 const ui::MotionEvent& event) {
748 return selection_controller_ &&
749 selection_controller_->WillHandleTouchEvent(event);
752 void RenderWidgetHostViewAndroid::ResetGestureDetection() {
753 const ui::MotionEvent* current_down_event =
754 gesture_provider_.GetCurrentDownEvent();
755 if (!current_down_event) {
756 // A hard reset ensures prevention of any timer-based events that might fire
757 // after a touch sequence has ended.
758 gesture_provider_.ResetDetection();
759 return;
762 scoped_ptr<ui::MotionEvent> cancel_event = current_down_event->Cancel();
763 if (gesture_provider_.OnTouchEvent(*cancel_event).succeeded) {
764 bool causes_scrolling = false;
765 host_->ForwardTouchEventWithLatencyInfo(
766 ui::CreateWebTouchEventFromMotionEvent(*cancel_event, causes_scrolling),
767 ui::LatencyInfo());
771 void RenderWidgetHostViewAndroid::OnDidNavigateMainFrameToNewPage() {
772 ResetGestureDetection();
775 void RenderWidgetHostViewAndroid::SetDoubleTapSupportEnabled(bool enabled) {
776 gesture_provider_.SetDoubleTapSupportForPlatformEnabled(enabled);
779 void RenderWidgetHostViewAndroid::SetMultiTouchZoomSupportEnabled(
780 bool enabled) {
781 gesture_provider_.SetMultiTouchZoomSupportEnabled(enabled);
784 void RenderWidgetHostViewAndroid::ImeCancelComposition() {
785 ime_adapter_android_.CancelComposition();
788 void RenderWidgetHostViewAndroid::ImeCompositionRangeChanged(
789 const gfx::Range& range,
790 const std::vector<gfx::Rect>& character_bounds) {
791 // TODO(yukawa): Implement this.
794 void RenderWidgetHostViewAndroid::FocusedNodeChanged(bool is_editable_node) {
795 ime_adapter_android_.FocusedNodeChanged(is_editable_node);
798 void RenderWidgetHostViewAndroid::RenderProcessGone(
799 base::TerminationStatus status, int error_code) {
800 Destroy();
803 void RenderWidgetHostViewAndroid::Destroy() {
804 RemoveLayers();
805 SetContentViewCore(NULL);
807 if (!surface_id_.is_null()) {
808 DCHECK(surface_factory_.get());
809 surface_factory_->Destroy(surface_id_);
810 surface_id_ = cc::SurfaceId();
812 surface_factory_.reset();
814 // The RenderWidgetHost's destruction led here, so don't call it.
815 host_ = NULL;
817 delete this;
820 void RenderWidgetHostViewAndroid::SetTooltipText(
821 const base::string16& tooltip_text) {
822 // Tooltips don't makes sense on Android.
825 void RenderWidgetHostViewAndroid::SelectionChanged(const base::string16& text,
826 size_t offset,
827 const gfx::Range& range) {
828 RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
830 if (!content_view_core_)
831 return;
832 if (range.is_empty()) {
833 content_view_core_->OnSelectionChanged("");
834 return;
837 DCHECK(!text.empty());
838 size_t pos = range.GetMin() - offset;
839 size_t n = range.length();
841 DCHECK(pos + n <= text.length()) << "The text can not fully cover range.";
842 if (pos >= text.length()) {
843 NOTREACHED() << "The text can not cover range.";
844 return;
847 std::string utf8_selection = base::UTF16ToUTF8(text.substr(pos, n));
849 content_view_core_->OnSelectionChanged(utf8_selection);
852 void RenderWidgetHostViewAndroid::SelectionBoundsChanged(
853 const ViewHostMsg_SelectionBounds_Params& params) {
854 NOTREACHED() << "Selection bounds should be routed through the compositor.";
857 void RenderWidgetHostViewAndroid::SetBackgroundColor(SkColor color) {
858 RenderWidgetHostViewBase::SetBackgroundColor(color);
859 host_->SetBackgroundOpaque(GetBackgroundOpaque());
860 UpdateBackgroundColor(color);
863 void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
864 const gfx::Rect& src_subrect,
865 const gfx::Size& dst_size,
866 ReadbackRequestCallback& callback,
867 const SkColorType preferred_color_type) {
868 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurface");
869 if (!host_ || host_->is_hidden()) {
870 callback.Run(SkBitmap(), READBACK_SURFACE_UNAVAILABLE);
871 return;
873 base::TimeTicks start_time = base::TimeTicks::Now();
874 if (using_browser_compositor_ && !IsSurfaceAvailableForCopy()) {
875 callback.Run(SkBitmap(), READBACK_SURFACE_UNAVAILABLE);
876 return;
878 const gfx::Display& display =
879 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
880 float device_scale_factor = display.device_scale_factor();
881 gfx::Size dst_size_in_pixel =
882 gfx::ConvertRectToPixel(device_scale_factor, gfx::Rect(dst_size)).size();
883 gfx::Rect src_subrect_in_pixel =
884 gfx::ConvertRectToPixel(device_scale_factor, src_subrect);
886 if (!using_browser_compositor_) {
887 SynchronousCopyContents(src_subrect_in_pixel, dst_size_in_pixel, callback,
888 preferred_color_type);
889 UMA_HISTOGRAM_TIMES("Compositing.CopyFromSurfaceTimeSynchronous",
890 base::TimeTicks::Now() - start_time);
891 return;
894 scoped_ptr<cc::CopyOutputRequest> request;
895 scoped_refptr<cc::Layer> readback_layer;
896 DCHECK(content_view_core_window_android_);
897 ui::WindowAndroidCompositor* compositor =
898 content_view_core_window_android_->GetCompositor();
899 DCHECK(compositor);
900 DCHECK(frame_provider_.get() || !surface_id_.is_null());
901 scoped_refptr<cc::Layer> layer = CreateDelegatedLayer();
902 DCHECK(layer);
903 layer->SetHideLayerAndSubtree(true);
904 compositor->AttachLayerForReadback(layer);
906 readback_layer = layer;
907 request = cc::CopyOutputRequest::CreateRequest(
908 base::Bind(&RenderWidgetHostViewAndroid::
909 PrepareTextureCopyOutputResultForDelegatedReadback,
910 dst_size_in_pixel, preferred_color_type, start_time,
911 readback_layer, callback));
912 if (!src_subrect_in_pixel.IsEmpty())
913 request->set_area(src_subrect_in_pixel);
914 readback_layer->RequestCopyOfOutput(request.Pass());
917 void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame(
918 const gfx::Rect& src_subrect,
919 const scoped_refptr<media::VideoFrame>& target,
920 const base::Callback<void(bool)>& callback) {
921 NOTIMPLEMENTED();
922 callback.Run(false);
925 bool RenderWidgetHostViewAndroid::CanCopyToVideoFrame() const {
926 return false;
929 void RenderWidgetHostViewAndroid::ShowDisambiguationPopup(
930 const gfx::Rect& rect_pixels, const SkBitmap& zoomed_bitmap) {
931 if (!content_view_core_)
932 return;
934 content_view_core_->ShowDisambiguationPopup(rect_pixels, zoomed_bitmap);
937 scoped_ptr<SyntheticGestureTarget>
938 RenderWidgetHostViewAndroid::CreateSyntheticGestureTarget() {
939 return scoped_ptr<SyntheticGestureTarget>(new SyntheticGestureTargetAndroid(
940 host_, content_view_core_->CreateMotionEventSynthesizer()));
943 void RenderWidgetHostViewAndroid::SendDelegatedFrameAck(
944 uint32 output_surface_id) {
945 DCHECK(host_);
946 cc::CompositorFrameAck ack;
947 if (!surface_returned_resources_.empty())
948 ack.resources.swap(surface_returned_resources_);
949 if (resource_collection_.get())
950 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
951 host_->Send(new ViewMsg_SwapCompositorFrameAck(host_->GetRoutingID(),
952 output_surface_id, ack));
955 void RenderWidgetHostViewAndroid::SendReturnedDelegatedResources(
956 uint32 output_surface_id) {
957 DCHECK(host_);
958 cc::CompositorFrameAck ack;
959 if (!surface_returned_resources_.empty()) {
960 ack.resources.swap(surface_returned_resources_);
961 } else {
962 DCHECK(resource_collection_.get());
963 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
966 host_->Send(new ViewMsg_ReclaimCompositorResources(host_->GetRoutingID(),
967 output_surface_id, ack));
970 void RenderWidgetHostViewAndroid::UnusedResourcesAreAvailable() {
971 DCHECK(surface_id_.is_null());
972 if (ack_callbacks_.size())
973 return;
974 SendReturnedDelegatedResources(last_output_surface_id_);
977 void RenderWidgetHostViewAndroid::ReturnResources(
978 const cc::ReturnedResourceArray& resources) {
979 if (resources.empty())
980 return;
981 std::copy(resources.begin(), resources.end(),
982 std::back_inserter(surface_returned_resources_));
983 if (!ack_callbacks_.size())
984 SendReturnedDelegatedResources(last_output_surface_id_);
987 void RenderWidgetHostViewAndroid::DestroyDelegatedContent() {
988 RemoveLayers();
989 frame_provider_ = NULL;
990 if (!surface_id_.is_null()) {
991 DCHECK(surface_factory_.get());
992 surface_factory_->Destroy(surface_id_);
993 surface_id_ = cc::SurfaceId();
995 layer_ = NULL;
998 void RenderWidgetHostViewAndroid::CheckOutputSurfaceChanged(
999 uint32 output_surface_id) {
1000 if (output_surface_id == last_output_surface_id_)
1001 return;
1002 // Drop the cc::DelegatedFrameResourceCollection so that we will not return
1003 // any resources from the old output surface with the new output surface id.
1004 if (resource_collection_.get()) {
1005 resource_collection_->SetClient(NULL);
1006 if (resource_collection_->LoseAllResources())
1007 SendReturnedDelegatedResources(last_output_surface_id_);
1008 resource_collection_ = NULL;
1010 DestroyDelegatedContent();
1011 surface_factory_.reset();
1012 if (!surface_returned_resources_.empty())
1013 SendReturnedDelegatedResources(last_output_surface_id_);
1015 last_output_surface_id_ = output_surface_id;
1018 void RenderWidgetHostViewAndroid::SubmitCompositorFrame(
1019 scoped_ptr<cc::CompositorFrame> frame) {
1020 cc::SurfaceManager* manager = CompositorImpl::GetSurfaceManager();
1021 if (manager) {
1022 if (!surface_factory_) {
1023 surface_factory_ = make_scoped_ptr(new cc::SurfaceFactory(manager, this));
1025 if (surface_id_.is_null() ||
1026 texture_size_in_layer_ != current_surface_size_ ||
1027 location_bar_content_translation_ !=
1028 frame->metadata.location_bar_content_translation ||
1029 current_viewport_selection_ != frame->metadata.selection) {
1030 RemoveLayers();
1031 if (!surface_id_.is_null())
1032 surface_factory_->Destroy(surface_id_);
1033 surface_id_ = id_allocator_->GenerateId();
1034 surface_factory_->Create(surface_id_);
1035 layer_ = CreateDelegatedLayer();
1037 DCHECK(layer_);
1039 current_surface_size_ = texture_size_in_layer_;
1040 location_bar_content_translation_ =
1041 frame->metadata.location_bar_content_translation;
1042 current_viewport_selection_ = frame->metadata.selection;
1043 AttachLayers();
1046 cc::SurfaceFactory::DrawCallback ack_callback =
1047 base::Bind(&RenderWidgetHostViewAndroid::RunAckCallbacks,
1048 weak_ptr_factory_.GetWeakPtr());
1049 surface_factory_->SubmitCompositorFrame(surface_id_, frame.Pass(),
1050 ack_callback);
1051 } else {
1052 if (!resource_collection_.get()) {
1053 resource_collection_ = new cc::DelegatedFrameResourceCollection;
1054 resource_collection_->SetClient(this);
1056 if (!frame_provider_.get() ||
1057 texture_size_in_layer_ != frame_provider_->frame_size()) {
1058 RemoveLayers();
1059 frame_provider_ = new cc::DelegatedFrameProvider(
1060 resource_collection_.get(), frame->delegated_frame_data.Pass());
1061 layer_ = cc::DelegatedRendererLayer::Create(Compositor::LayerSettings(),
1062 frame_provider_);
1063 AttachLayers();
1064 } else {
1065 frame_provider_->SetFrameData(frame->delegated_frame_data.Pass());
1070 void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
1071 uint32 output_surface_id,
1072 scoped_ptr<cc::CompositorFrame> frame) {
1073 CheckOutputSurfaceChanged(output_surface_id);
1074 bool has_content = !texture_size_in_layer_.IsEmpty();
1076 // DelegatedRendererLayerImpl applies the inverse device_scale_factor of the
1077 // renderer frame, assuming that the browser compositor will scale
1078 // it back up to device scale. But on Android we put our browser layers in
1079 // physical pixels and set our browser CC device_scale_factor to 1, so this
1080 // suppresses the transform. This line may need to be removed when fixing
1081 // http://crbug.com/384134 or http://crbug.com/310763
1082 frame->delegated_frame_data->device_scale_factor = 1.0f;
1084 base::Closure ack_callback =
1085 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck,
1086 weak_ptr_factory_.GetWeakPtr(),
1087 output_surface_id);
1089 ack_callbacks_.push(ack_callback);
1091 if (!has_content) {
1092 DestroyDelegatedContent();
1093 } else {
1094 SubmitCompositorFrame(frame.Pass());
1097 if (layer_.get()) {
1098 layer_->SetIsDrawable(true);
1099 layer_->SetContentsOpaque(true);
1100 layer_->SetBounds(texture_size_in_layer_);
1103 if (host_->is_hidden())
1104 RunAckCallbacks(cc::SurfaceDrawStatus::DRAW_SKIPPED);
1107 void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame(
1108 uint32 output_surface_id,
1109 scoped_ptr<cc::CompositorFrame> frame) {
1110 last_scroll_offset_ = frame->metadata.root_scroll_offset;
1111 if (!frame->delegated_frame_data) {
1112 LOG(ERROR) << "Non-delegated renderer path no longer supported";
1113 return;
1116 if (locks_on_frame_count_ > 0) {
1117 DCHECK(HasValidFrame());
1118 RetainFrame(output_surface_id, frame.Pass());
1119 return;
1122 if (!CompositorImpl::GetSurfaceManager() && layer_.get() &&
1123 layer_->layer_tree_host()) {
1124 for (size_t i = 0; i < frame->metadata.latency_info.size(); i++) {
1125 scoped_ptr<cc::SwapPromise> swap_promise(
1126 new cc::LatencyInfoSwapPromise(frame->metadata.latency_info[i]));
1127 layer_->layer_tree_host()->QueueSwapPromise(swap_promise.Pass());
1131 DCHECK(!frame->delegated_frame_data->render_pass_list.empty());
1133 cc::RenderPass* root_pass =
1134 frame->delegated_frame_data->render_pass_list.back();
1135 texture_size_in_layer_ = root_pass->output_rect.size();
1137 cc::CompositorFrameMetadata metadata = frame->metadata;
1139 SwapDelegatedFrame(output_surface_id, frame.Pass());
1140 frame_evictor_->SwappedFrame(!host_->is_hidden());
1142 // As the metadata update may trigger view invalidation, always call it after
1143 // any potential compositor scheduling.
1144 OnFrameMetadataUpdated(metadata);
1147 void RenderWidgetHostViewAndroid::OnSwapCompositorFrame(
1148 uint32 output_surface_id,
1149 scoped_ptr<cc::CompositorFrame> frame) {
1150 InternalSwapCompositorFrame(output_surface_id, frame.Pass());
1153 void RenderWidgetHostViewAndroid::ClearCompositorFrame() {
1154 DestroyDelegatedContent();
1157 void RenderWidgetHostViewAndroid::RetainFrame(
1158 uint32 output_surface_id,
1159 scoped_ptr<cc::CompositorFrame> frame) {
1160 DCHECK(locks_on_frame_count_);
1162 // Store the incoming frame so that it can be swapped when all the locks have
1163 // been released. If there is already a stored frame, then replace and skip
1164 // the previous one but make sure we still eventually send the ACK. Holding
1165 // the ACK also blocks the renderer when its max_frames_pending is reached.
1166 if (last_frame_info_) {
1167 base::Closure ack_callback =
1168 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck,
1169 weak_ptr_factory_.GetWeakPtr(),
1170 last_frame_info_->output_surface_id);
1172 ack_callbacks_.push(ack_callback);
1175 last_frame_info_.reset(new LastFrameInfo(output_surface_id, frame.Pass()));
1178 void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
1179 const cc::CompositorFrameMetadata& frame_metadata) {
1180 if (!content_view_core_)
1181 return;
1183 // This is a subset of OnSwapCompositorFrame() used in the synchronous
1184 // compositor flow.
1185 OnFrameMetadataUpdated(frame_metadata);
1187 // DevTools ScreenCast support for Android WebView.
1188 WebContents* web_contents = content_view_core_->GetWebContents();
1189 if (DevToolsAgentHost::HasFor(web_contents)) {
1190 scoped_refptr<DevToolsAgentHost> dtah =
1191 DevToolsAgentHost::GetOrCreateFor(web_contents);
1192 // Unblock the compositor.
1193 BrowserThread::PostTask(
1194 BrowserThread::UI, FROM_HERE,
1195 base::Bind(
1196 &RenderFrameDevToolsAgentHost::SynchronousSwapCompositorFrame,
1197 static_cast<RenderFrameDevToolsAgentHost*>(dtah.get()),
1198 frame_metadata));
1202 void RenderWidgetHostViewAndroid::SetOverlayVideoMode(bool enabled) {
1203 if (layer_.get())
1204 layer_->SetContentsOpaque(!enabled);
1207 bool RenderWidgetHostViewAndroid::SupportsAnimation() const {
1208 // The synchronous (WebView) compositor does not have a proper browser
1209 // compositor with which to drive animations.
1210 return using_browser_compositor_;
1213 void RenderWidgetHostViewAndroid::SetNeedsAnimate() {
1214 DCHECK(content_view_core_window_android_);
1215 DCHECK(using_browser_compositor_);
1216 content_view_core_window_android_->SetNeedsAnimate();
1219 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::PointF& position) {
1220 MoveCaret(gfx::Point(position.x(), position.y()));
1223 void RenderWidgetHostViewAndroid::MoveRangeSelectionExtent(
1224 const gfx::PointF& extent) {
1225 DCHECK(content_view_core_);
1226 content_view_core_->MoveRangeSelectionExtent(extent);
1229 void RenderWidgetHostViewAndroid::SelectBetweenCoordinates(
1230 const gfx::PointF& base,
1231 const gfx::PointF& extent) {
1232 DCHECK(content_view_core_);
1233 content_view_core_->SelectBetweenCoordinates(base, extent);
1236 void RenderWidgetHostViewAndroid::OnSelectionEvent(
1237 ui::SelectionEventType event) {
1238 DCHECK(content_view_core_);
1239 DCHECK(selection_controller_);
1240 // If a selection drag has started, it has taken over the active touch
1241 // sequence. Immediately cancel gesture detection and any downstream touch
1242 // listeners (e.g., web content) to communicate this transfer.
1243 if (event == ui::SELECTION_HANDLES_SHOWN)
1244 ResetGestureDetection();
1245 content_view_core_->OnSelectionEvent(
1246 event, selection_controller_->GetStartPosition(),
1247 GetSelectionRect(*selection_controller_));
1250 scoped_ptr<ui::TouchHandleDrawable>
1251 RenderWidgetHostViewAndroid::CreateDrawable() {
1252 DCHECK(content_view_core_);
1253 if (!using_browser_compositor_)
1254 return PopupTouchHandleDrawable::Create(content_view_core_);
1256 return scoped_ptr<ui::TouchHandleDrawable>(new CompositedTouchHandleDrawable(
1257 content_view_core_->GetLayer().get(),
1258 content_view_core_->GetDpiScale(),
1259 // Use the activity context (instead of the application context) to ensure
1260 // proper handle theming.
1261 content_view_core_->GetContext().obj()));
1264 void RenderWidgetHostViewAndroid::SynchronousCopyContents(
1265 const gfx::Rect& src_subrect_in_pixel,
1266 const gfx::Size& dst_size_in_pixel,
1267 ReadbackRequestCallback& callback,
1268 const SkColorType color_type) {
1269 gfx::Size input_size_in_pixel;
1270 if (src_subrect_in_pixel.IsEmpty())
1271 input_size_in_pixel = texture_size_in_layer_;
1272 else
1273 input_size_in_pixel = src_subrect_in_pixel.size();
1275 gfx::Size output_size_in_pixel;
1276 if (dst_size_in_pixel.IsEmpty())
1277 output_size_in_pixel = input_size_in_pixel;
1278 else
1279 output_size_in_pixel = dst_size_in_pixel;
1280 int output_width = output_size_in_pixel.width();
1281 int output_height = output_size_in_pixel.height();
1283 SynchronousCompositor* compositor =
1284 SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
1285 host_->GetRoutingID());
1286 if (!compositor) {
1287 callback.Run(SkBitmap(), READBACK_FAILED);
1288 return;
1291 SkBitmap bitmap;
1292 bitmap.allocPixels(SkImageInfo::Make(output_width,
1293 output_height,
1294 color_type,
1295 kPremul_SkAlphaType));
1296 SkCanvas canvas(bitmap);
1297 canvas.scale(
1298 (float)output_width / (float)input_size_in_pixel.width(),
1299 (float)output_height / (float)input_size_in_pixel.height());
1300 compositor->DemandDrawSw(&canvas);
1301 callback.Run(bitmap, READBACK_SUCCESS);
1304 void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
1305 const cc::CompositorFrameMetadata& frame_metadata) {
1306 bool is_mobile_optimized = IsMobileOptimizedFrame(frame_metadata);
1307 gesture_provider_.SetDoubleTapSupportForPageEnabled(!is_mobile_optimized);
1309 if (!content_view_core_)
1310 return;
1312 if (overscroll_controller_)
1313 overscroll_controller_->OnFrameMetadataUpdated(frame_metadata);
1315 if (selection_controller_) {
1316 selection_controller_->OnSelectionEditable(
1317 frame_metadata.selection.is_editable);
1318 selection_controller_->OnSelectionEmpty(
1319 frame_metadata.selection.is_empty_text_form_control);
1320 selection_controller_->OnSelectionBoundsChanged(
1321 ConvertSelectionBound(frame_metadata.selection.start),
1322 ConvertSelectionBound(frame_metadata.selection.end));
1325 UpdateBackgroundColor(frame_metadata.root_background_color);
1327 // All offsets and sizes are in CSS pixels.
1328 content_view_core_->UpdateFrameInfo(
1329 frame_metadata.root_scroll_offset,
1330 frame_metadata.page_scale_factor,
1331 gfx::Vector2dF(frame_metadata.min_page_scale_factor,
1332 frame_metadata.max_page_scale_factor),
1333 frame_metadata.root_layer_size,
1334 frame_metadata.scrollable_viewport_size,
1335 frame_metadata.location_bar_offset,
1336 frame_metadata.location_bar_content_translation,
1337 is_mobile_optimized);
1338 #if defined(VIDEO_HOLE)
1339 if (host_ && host_->IsRenderView()) {
1340 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
1341 RenderViewHost::From(host_));
1342 WebContentsImpl* web_contents_impl =
1343 static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(rvhi));
1344 if (web_contents_impl)
1345 web_contents_impl->media_web_contents_observer()->OnFrameInfoUpdated();
1347 #endif // defined(VIDEO_HOLE)
1350 void RenderWidgetHostViewAndroid::AcceleratedSurfaceInitialized(int route_id) {
1351 // TODO: remove need for the surface id here
1352 accelerated_surface_route_id_ = route_id;
1355 void RenderWidgetHostViewAndroid::ShowInternal() {
1356 DCHECK(is_showing_);
1357 if (!host_ || !host_->is_hidden())
1358 return;
1360 if (layer_.get())
1361 layer_->SetHideLayerAndSubtree(false);
1363 frame_evictor_->SetVisible(true);
1365 if (overscroll_controller_)
1366 overscroll_controller_->Enable();
1368 host_->WasShown(ui::LatencyInfo());
1370 if (content_view_core_) {
1371 StartObservingRootWindow();
1372 RequestVSyncUpdate(BEGIN_FRAME);
1376 void RenderWidgetHostViewAndroid::HideInternal(
1377 bool hide_frontbuffer,
1378 bool stop_observing_root_window) {
1379 if (hide_frontbuffer) {
1380 if (layer_.get() && locks_on_frame_count_ == 0)
1381 layer_->SetHideLayerAndSubtree(true);
1383 frame_evictor_->SetVisible(false);
1386 if (stop_observing_root_window)
1387 StopObservingRootWindow();
1389 if (!host_ || host_->is_hidden())
1390 return;
1392 if (overscroll_controller_)
1393 overscroll_controller_->Disable();
1395 RunAckCallbacks(cc::SurfaceDrawStatus::DRAW_SKIPPED);
1397 // Inform the renderer that we are being hidden so it can reduce its resource
1398 // utilization.
1399 host_->WasHidden();
1402 void RenderWidgetHostViewAndroid::AttachLayers() {
1403 if (!content_view_core_)
1404 return;
1405 if (!layer_.get())
1406 return;
1408 content_view_core_->AttachLayer(layer_);
1409 layer_->SetHideLayerAndSubtree(!is_showing_);
1412 void RenderWidgetHostViewAndroid::RemoveLayers() {
1413 if (!content_view_core_)
1414 return;
1416 if (!layer_.get())
1417 return;
1419 content_view_core_->RemoveLayer(layer_);
1422 void RenderWidgetHostViewAndroid::RequestVSyncUpdate(uint32 requests) {
1423 bool should_request_vsync = !outstanding_vsync_requests_ && requests;
1424 outstanding_vsync_requests_ |= requests;
1426 // If the host has been hidden, defer vsync requests until it is shown
1427 // again via |Show()|.
1428 if (!host_ || host_->is_hidden())
1429 return;
1431 // Note that if we're not currently observing the root window, outstanding
1432 // vsync requests will be pushed if/when we resume observing in
1433 // |StartObservingRootWindow()|.
1434 if (observing_root_window_ && should_request_vsync)
1435 content_view_core_window_android_->RequestVSyncUpdate();
1438 void RenderWidgetHostViewAndroid::StartObservingRootWindow() {
1439 DCHECK(content_view_core_window_android_);
1440 DCHECK(is_showing_);
1441 if (observing_root_window_)
1442 return;
1444 observing_root_window_ = true;
1445 content_view_core_window_android_->AddObserver(this);
1447 // Clear existing vsync requests to allow a request to the new window.
1448 uint32 outstanding_vsync_requests = outstanding_vsync_requests_;
1449 outstanding_vsync_requests_ = 0;
1450 RequestVSyncUpdate(outstanding_vsync_requests);
1453 void RenderWidgetHostViewAndroid::StopObservingRootWindow() {
1454 if (!content_view_core_window_android_) {
1455 DCHECK(!observing_root_window_);
1456 return;
1459 if (!observing_root_window_)
1460 return;
1462 observing_root_window_ = false;
1463 content_view_core_window_android_->RemoveObserver(this);
1466 void RenderWidgetHostViewAndroid::SendBeginFrame(base::TimeTicks frame_time,
1467 base::TimeDelta vsync_period) {
1468 TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::SendBeginFrame",
1469 "frame_time_us", frame_time.ToInternalValue());
1471 if (using_browser_compositor_) {
1472 // TODO(brianderson): Replace this hardcoded deadline after Android
1473 // switches to Surfaces and the Browser's commit isn't in the critcal path.
1474 base::TimeTicks deadline = frame_time + (vsync_period * 0.6);
1476 host_->Send(new ViewMsg_BeginFrame(
1477 host_->GetRoutingID(),
1478 cc::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline,
1479 vsync_period, cc::BeginFrameArgs::NORMAL)));
1480 } else {
1481 SynchronousCompositorImpl* compositor = SynchronousCompositorImpl::FromID(
1482 host_->GetProcess()->GetID(), host_->GetRoutingID());
1483 if (compositor) {
1484 // The synchronous compositor synchronously does it's work in this call.
1485 // It does not use a deadline.
1486 compositor->BeginFrame(cc::BeginFrameArgs::Create(
1487 BEGINFRAME_FROM_HERE, frame_time, base::TimeTicks(), vsync_period,
1488 cc::BeginFrameArgs::NORMAL));
1493 bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) {
1494 bool needs_animate = false;
1495 if (overscroll_controller_) {
1496 needs_animate |= overscroll_controller_->Animate(
1497 frame_time, content_view_core_->GetLayer().get());
1499 if (selection_controller_)
1500 needs_animate |= selection_controller_->Animate(frame_time);
1501 return needs_animate;
1504 void RenderWidgetHostViewAndroid::RequestDisallowInterceptTouchEvent() {
1505 if (content_view_core_)
1506 content_view_core_->RequestDisallowInterceptTouchEvent();
1509 void RenderWidgetHostViewAndroid::EvictDelegatedFrame() {
1510 if (layer_.get())
1511 DestroyDelegatedContent();
1512 frame_evictor_->DiscardedFrame();
1515 bool RenderWidgetHostViewAndroid::HasAcceleratedSurface(
1516 const gfx::Size& desired_size) {
1517 NOTREACHED();
1518 return false;
1521 void RenderWidgetHostViewAndroid::GetScreenInfo(blink::WebScreenInfo* result) {
1522 // ScreenInfo isn't tied to the widget on Android. Always return the default.
1523 RenderWidgetHostViewBase::GetDefaultScreenInfo(result);
1526 bool RenderWidgetHostViewAndroid::GetScreenColorProfile(
1527 std::vector<char>* color_profile) {
1528 DCHECK(color_profile->empty());
1529 NOTREACHED();
1530 return false;
1533 // TODO(jrg): Find out the implications and answer correctly here,
1534 // as we are returning the WebView and not root window bounds.
1535 gfx::Rect RenderWidgetHostViewAndroid::GetBoundsInRootWindow() {
1536 return GetViewBounds();
1539 gfx::GLSurfaceHandle RenderWidgetHostViewAndroid::GetCompositingSurface() {
1540 gfx::GLSurfaceHandle handle =
1541 gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NULL_TRANSPORT);
1542 // Null check for when we're running inside content_unittests.
1543 if (using_browser_compositor_ && BrowserGpuChannelHostFactory::instance()) {
1544 handle.parent_client_id =
1545 BrowserGpuChannelHostFactory::instance()->GetGpuChannelId();
1547 return handle;
1550 void RenderWidgetHostViewAndroid::ProcessAckedTouchEvent(
1551 const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
1552 const bool event_consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
1553 gesture_provider_.OnTouchEventAck(touch.event.uniqueTouchEventId,
1554 event_consumed);
1557 void RenderWidgetHostViewAndroid::GestureEventAck(
1558 const blink::WebGestureEvent& event,
1559 InputEventAckState ack_result) {
1560 if (overscroll_controller_)
1561 overscroll_controller_->OnGestureEventAck(event, ack_result);
1563 if (content_view_core_)
1564 content_view_core_->OnGestureEventAck(event, ack_result);
1567 InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
1568 const blink::WebInputEvent& input_event) {
1569 if (selection_controller_ &&
1570 blink::WebInputEvent::isGestureEventType(input_event.type)) {
1571 const blink::WebGestureEvent& gesture_event =
1572 static_cast<const blink::WebGestureEvent&>(input_event);
1573 switch (gesture_event.type) {
1574 case blink::WebInputEvent::GestureLongPress:
1575 if (selection_controller_->WillHandleLongPressEvent(
1576 base::TimeTicks() +
1577 base::TimeDelta::FromSecondsD(input_event.timeStampSeconds),
1578 gfx::PointF(gesture_event.x, gesture_event.y))) {
1579 return INPUT_EVENT_ACK_STATE_CONSUMED;
1581 break;
1583 case blink::WebInputEvent::GestureTap:
1584 if (selection_controller_->WillHandleTapEvent(
1585 gfx::PointF(gesture_event.x, gesture_event.y))) {
1586 return INPUT_EVENT_ACK_STATE_CONSUMED;
1588 break;
1590 default:
1591 break;
1595 if (overscroll_controller_ &&
1596 blink::WebInputEvent::isGestureEventType(input_event.type) &&
1597 overscroll_controller_->WillHandleGestureEvent(
1598 static_cast<const blink::WebGestureEvent&>(input_event))) {
1599 return INPUT_EVENT_ACK_STATE_CONSUMED;
1602 if (content_view_core_ && content_view_core_->FilterInputEvent(input_event))
1603 return INPUT_EVENT_ACK_STATE_CONSUMED;
1605 if (!host_)
1606 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1608 if (input_event.type == blink::WebInputEvent::GestureTapDown ||
1609 input_event.type == blink::WebInputEvent::TouchStart) {
1610 GpuDataManagerImpl* gpu_data = GpuDataManagerImpl::GetInstance();
1611 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance();
1612 if (shim && gpu_data && accelerated_surface_route_id_ &&
1613 gpu_data->IsDriverBugWorkaroundActive(gpu::WAKE_UP_GPU_BEFORE_DRAWING))
1614 shim->Send(
1615 new AcceleratedSurfaceMsg_WakeUpGpu(accelerated_surface_route_id_));
1618 SynchronousCompositorImpl* compositor =
1619 SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
1620 host_->GetRoutingID());
1621 if (compositor)
1622 return compositor->HandleInputEvent(input_event);
1623 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1626 void RenderWidgetHostViewAndroid::OnSetNeedsFlushInput() {
1627 TRACE_EVENT0("input", "RenderWidgetHostViewAndroid::OnSetNeedsFlushInput");
1628 RequestVSyncUpdate(FLUSH_INPUT);
1631 BrowserAccessibilityManager*
1632 RenderWidgetHostViewAndroid::CreateBrowserAccessibilityManager(
1633 BrowserAccessibilityDelegate* delegate) {
1634 // TODO(dmazzoni): Currently there can only be one
1635 // BrowserAccessibilityManager per ContentViewCore, so return NULL
1636 // if there's already a BrowserAccessibilityManager for the main
1637 // frame. Eventually, in order to support cross-process iframes on
1638 // Android we'll need to add support for a
1639 // BrowserAccessibilityManager for a child frame.
1640 // http://crbug.com/423846
1641 if (!host_ || host_->GetRootBrowserAccessibilityManager())
1642 return NULL;
1644 base::android::ScopedJavaLocalRef<jobject> obj;
1645 if (content_view_core_)
1646 obj = content_view_core_->GetJavaObject();
1647 return new BrowserAccessibilityManagerAndroid(
1648 obj,
1649 BrowserAccessibilityManagerAndroid::GetEmptyDocument(),
1650 delegate);
1653 bool RenderWidgetHostViewAndroid::LockMouse() {
1654 NOTIMPLEMENTED();
1655 return false;
1658 void RenderWidgetHostViewAndroid::UnlockMouse() {
1659 NOTIMPLEMENTED();
1662 // Methods called from the host to the render
1664 void RenderWidgetHostViewAndroid::SendKeyEvent(
1665 const NativeWebKeyboardEvent& event) {
1666 if (host_)
1667 host_->ForwardKeyboardEvent(event);
1670 void RenderWidgetHostViewAndroid::SendMouseEvent(
1671 const blink::WebMouseEvent& event) {
1672 if (host_)
1673 host_->ForwardMouseEvent(event);
1676 void RenderWidgetHostViewAndroid::SendMouseWheelEvent(
1677 const blink::WebMouseWheelEvent& event) {
1678 if (host_)
1679 host_->ForwardWheelEvent(event);
1682 void RenderWidgetHostViewAndroid::SendGestureEvent(
1683 const blink::WebGestureEvent& event) {
1684 // Sending a gesture that may trigger overscroll should resume the effect.
1685 if (overscroll_controller_)
1686 overscroll_controller_->Enable();
1688 if (host_)
1689 host_->ForwardGestureEventWithLatencyInfo(event, ui::LatencyInfo());
1692 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point& point) {
1693 if (host_)
1694 host_->MoveCaret(point);
1697 void RenderWidgetHostViewAndroid::DismissTextHandles() {
1698 if (selection_controller_)
1699 selection_controller_->HideAndDisallowShowingAutomatically();
1702 void RenderWidgetHostViewAndroid::SetTextHandlesTemporarilyHidden(bool hidden) {
1703 if (selection_controller_)
1704 selection_controller_->SetTemporarilyHidden(hidden);
1707 void RenderWidgetHostViewAndroid::OnShowingPastePopup(
1708 const gfx::PointF& point) {
1709 if (!selection_controller_)
1710 return;
1712 // As the paste popup may be triggered *before* the bounds and editability
1713 // of the region have been updated, explicitly set the properties now.
1714 // TODO(jdduke): Remove this workaround when auxiliary paste popup
1715 // notifications are no longer required, crbug.com/398170.
1716 ui::SelectionBound insertion_bound;
1717 insertion_bound.set_type(ui::SelectionBound::CENTER);
1718 insertion_bound.set_visible(true);
1719 insertion_bound.SetEdge(point, point);
1720 selection_controller_->HideAndDisallowShowingAutomatically();
1721 selection_controller_->OnSelectionEditable(true);
1722 selection_controller_->OnSelectionEmpty(true);
1723 selection_controller_->OnSelectionBoundsChanged(insertion_bound,
1724 insertion_bound);
1725 selection_controller_->AllowShowingFromCurrentSelection();
1728 SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const {
1729 return cached_background_color_;
1732 void RenderWidgetHostViewAndroid::DidOverscroll(
1733 const DidOverscrollParams& params) {
1734 if (!content_view_core_ || !layer_.get() || !is_showing_)
1735 return;
1737 if (overscroll_controller_)
1738 overscroll_controller_->OnOverscrolled(params);
1741 void RenderWidgetHostViewAndroid::DidStopFlinging() {
1742 if (content_view_core_)
1743 content_view_core_->DidStopFlinging();
1746 uint32_t RenderWidgetHostViewAndroid::GetSurfaceIdNamespace() {
1747 if (id_allocator_)
1748 return id_allocator_->id_namespace();
1749 return 0;
1752 void RenderWidgetHostViewAndroid::SetContentViewCore(
1753 ContentViewCoreImpl* content_view_core) {
1754 RemoveLayers();
1755 StopObservingRootWindow();
1757 bool resize = false;
1758 if (content_view_core != content_view_core_) {
1759 overscroll_controller_.reset();
1760 selection_controller_.reset();
1761 ReleaseLocksOnSurface();
1762 resize = true;
1765 content_view_core_ = content_view_core;
1766 content_view_core_window_android_ =
1767 content_view_core_ ? content_view_core_->GetWindowAndroid() : nullptr;
1768 DCHECK_EQ(!!content_view_core_, !!content_view_core_window_android_);
1770 BrowserAccessibilityManager* manager = NULL;
1771 if (host_)
1772 manager = host_->GetRootBrowserAccessibilityManager();
1773 if (manager) {
1774 base::android::ScopedJavaLocalRef<jobject> obj;
1775 if (content_view_core_)
1776 obj = content_view_core_->GetJavaObject();
1777 manager->ToBrowserAccessibilityManagerAndroid()->SetContentViewCore(obj);
1780 AttachLayers();
1782 if (!content_view_core_)
1783 return;
1785 if (is_showing_)
1786 StartObservingRootWindow();
1788 if (resize)
1789 WasResized();
1791 if (!selection_controller_)
1792 selection_controller_ = CreateSelectionController(this, content_view_core_);
1794 if (!overscroll_controller_ &&
1795 content_view_core_window_android_->GetCompositor()) {
1796 overscroll_controller_ = CreateOverscrollController(content_view_core_);
1800 void RenderWidgetHostViewAndroid::RunAckCallbacks(
1801 cc::SurfaceDrawStatus status) {
1802 while (!ack_callbacks_.empty()) {
1803 ack_callbacks_.front().Run();
1804 ack_callbacks_.pop();
1808 void RenderWidgetHostViewAndroid::OnGestureEvent(
1809 const ui::GestureEventData& gesture) {
1810 blink::WebGestureEvent web_gesture =
1811 ui::CreateWebGestureEventFromGestureEventData(gesture);
1812 // TODO(jdduke): Remove this workaround after Android fixes UiAutomator to
1813 // stop providing shift meta values to synthetic MotionEvents. This prevents
1814 // unintended shift+click interpretation of all accessibility clicks.
1815 // See crbug.com/443247.
1816 if (web_gesture.type == blink::WebInputEvent::GestureTap &&
1817 web_gesture.modifiers == blink::WebInputEvent::ShiftKey) {
1818 web_gesture.modifiers = 0;
1820 SendGestureEvent(web_gesture);
1823 void RenderWidgetHostViewAndroid::OnCompositingDidCommit() {
1824 RunAckCallbacks(cc::SurfaceDrawStatus::DRAWN);
1827 void RenderWidgetHostViewAndroid::OnRootWindowVisibilityChanged(bool visible) {
1828 DCHECK(is_showing_);
1829 if (visible) {
1830 ShowInternal();
1831 } else {
1832 bool hide_frontbuffer = true;
1833 bool stop_observing_root_window = false;
1834 HideInternal(hide_frontbuffer, stop_observing_root_window);
1838 void RenderWidgetHostViewAndroid::OnAttachCompositor() {
1839 DCHECK(content_view_core_);
1840 if (!overscroll_controller_)
1841 overscroll_controller_ = CreateOverscrollController(content_view_core_);
1844 void RenderWidgetHostViewAndroid::OnDetachCompositor() {
1845 DCHECK(content_view_core_);
1846 DCHECK(using_browser_compositor_);
1847 RunAckCallbacks(cc::SurfaceDrawStatus::DRAW_SKIPPED);
1848 overscroll_controller_.reset();
1851 void RenderWidgetHostViewAndroid::OnVSync(base::TimeTicks frame_time,
1852 base::TimeDelta vsync_period) {
1853 TRACE_EVENT0("cc,benchmark", "RenderWidgetHostViewAndroid::OnVSync");
1854 if (!host_ || host_->is_hidden())
1855 return;
1857 if (outstanding_vsync_requests_ & FLUSH_INPUT) {
1858 outstanding_vsync_requests_ &= ~FLUSH_INPUT;
1859 host_->FlushInput();
1862 if (outstanding_vsync_requests_ & BEGIN_FRAME ||
1863 outstanding_vsync_requests_ & PERSISTENT_BEGIN_FRAME) {
1864 outstanding_vsync_requests_ &= ~BEGIN_FRAME;
1865 SendBeginFrame(frame_time, vsync_period);
1868 // This allows for SendBeginFrame and FlushInput to modify
1869 // outstanding_vsync_requests.
1870 uint32 outstanding_vsync_requests = outstanding_vsync_requests_;
1871 outstanding_vsync_requests_ = 0;
1872 RequestVSyncUpdate(outstanding_vsync_requests);
1875 void RenderWidgetHostViewAndroid::OnAnimate(base::TimeTicks begin_frame_time) {
1876 if (Animate(begin_frame_time))
1877 SetNeedsAnimate();
1880 void RenderWidgetHostViewAndroid::OnActivityStopped() {
1881 TRACE_EVENT0("browser", "RenderWidgetHostViewAndroid::OnActivityStopped");
1882 DCHECK(is_showing_);
1883 bool hide_frontbuffer = false;
1884 bool stop_observing_root_window = false;
1885 HideInternal(hide_frontbuffer, stop_observing_root_window);
1888 void RenderWidgetHostViewAndroid::OnActivityStarted() {
1889 TRACE_EVENT0("browser", "RenderWidgetHostViewAndroid::OnActivityStarted");
1890 DCHECK(is_showing_);
1891 ShowInternal();
1894 void RenderWidgetHostViewAndroid::OnLostResources() {
1895 ReleaseLocksOnSurface();
1896 if (layer_.get())
1897 DestroyDelegatedContent();
1898 DCHECK(ack_callbacks_.empty());
1901 // static
1902 void RenderWidgetHostViewAndroid::
1903 PrepareTextureCopyOutputResultForDelegatedReadback(
1904 const gfx::Size& dst_size_in_pixel,
1905 SkColorType color_type,
1906 const base::TimeTicks& start_time,
1907 scoped_refptr<cc::Layer> readback_layer,
1908 ReadbackRequestCallback& callback,
1909 scoped_ptr<cc::CopyOutputResult> result) {
1910 readback_layer->RemoveFromParent();
1911 PrepareTextureCopyOutputResult(
1912 dst_size_in_pixel, color_type, start_time, callback, result.Pass());
1915 // static
1916 void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
1917 const gfx::Size& dst_size_in_pixel,
1918 SkColorType color_type,
1919 const base::TimeTicks& start_time,
1920 ReadbackRequestCallback& callback,
1921 scoped_ptr<cc::CopyOutputResult> result) {
1922 base::ScopedClosureRunner scoped_callback_runner(
1923 base::Bind(callback, SkBitmap(), READBACK_FAILED));
1924 TRACE_EVENT0("cc",
1925 "RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult");
1927 if (!result->HasTexture() || result->IsEmpty() || result->size().IsEmpty())
1928 return;
1930 gfx::Size output_size_in_pixel;
1931 if (dst_size_in_pixel.IsEmpty())
1932 output_size_in_pixel = result->size();
1933 else
1934 output_size_in_pixel = dst_size_in_pixel;
1936 GLHelper* gl_helper = GetPostReadbackGLHelper();
1937 if (!gl_helper)
1938 return;
1939 if (!gl_helper->IsReadbackConfigSupported(color_type))
1940 color_type = kRGBA_8888_SkColorType;
1941 scoped_ptr<SkBitmap> bitmap(new SkBitmap);
1942 if (!bitmap->tryAllocPixels(SkImageInfo::Make(output_size_in_pixel.width(),
1943 output_size_in_pixel.height(),
1944 color_type,
1945 kOpaque_SkAlphaType))) {
1946 scoped_callback_runner.Reset(
1947 base::Bind(callback, SkBitmap(), READBACK_BITMAP_ALLOCATION_FAILURE));
1948 return;
1952 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock(
1953 new SkAutoLockPixels(*bitmap));
1954 uint8* pixels = static_cast<uint8*>(bitmap->getPixels());
1956 cc::TextureMailbox texture_mailbox;
1957 scoped_ptr<cc::SingleReleaseCallback> release_callback;
1958 result->TakeTexture(&texture_mailbox, &release_callback);
1959 DCHECK(texture_mailbox.IsTexture());
1960 if (!texture_mailbox.IsTexture())
1961 return;
1963 ignore_result(scoped_callback_runner.Release());
1965 gl_helper->CropScaleReadbackAndCleanMailbox(
1966 texture_mailbox.mailbox(),
1967 texture_mailbox.sync_point(),
1968 result->size(),
1969 gfx::Rect(result->size()),
1970 output_size_in_pixel,
1971 pixels,
1972 color_type,
1973 base::Bind(&CopyFromCompositingSurfaceFinished,
1974 callback,
1975 base::Passed(&release_callback),
1976 base::Passed(&bitmap),
1977 start_time,
1978 base::Passed(&bitmap_pixels_lock)),
1979 GLHelper::SCALER_QUALITY_GOOD);
1982 void RenderWidgetHostViewAndroid::OnStylusSelectBegin(float x0,
1983 float y0,
1984 float x1,
1985 float y1) {
1986 SelectBetweenCoordinates(gfx::PointF(x0, y0), gfx::PointF(x1, y1));
1989 void RenderWidgetHostViewAndroid::OnStylusSelectUpdate(float x, float y) {
1990 MoveRangeSelectionExtent(gfx::PointF(x, y));
1993 void RenderWidgetHostViewAndroid::OnStylusSelectEnd() {
1994 if (selection_controller_)
1995 selection_controller_->AllowShowingFromCurrentSelection();
1998 void RenderWidgetHostViewAndroid::OnStylusSelectTap(base::TimeTicks time,
1999 float x,
2000 float y) {
2001 // Treat the stylus tap as a long press, activating either a word selection or
2002 // context menu depending on the targetted content.
2003 blink::WebGestureEvent long_press = WebGestureEventBuilder::Build(
2004 blink::WebInputEvent::GestureLongPress,
2005 (time - base::TimeTicks()).InSecondsF(), x, y);
2006 SendGestureEvent(long_press);
2009 // static
2010 void RenderWidgetHostViewBase::GetDefaultScreenInfo(
2011 blink::WebScreenInfo* results) {
2012 const gfx::Display& display =
2013 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
2014 results->rect = display.bounds();
2015 // TODO(husky): Remove any system controls from availableRect.
2016 results->availableRect = display.work_area();
2017 results->deviceScaleFactor = display.device_scale_factor();
2018 results->orientationAngle = display.RotationAsDegree();
2019 results->orientationType =
2020 RenderWidgetHostViewBase::GetOrientationTypeForMobile(display);
2021 gfx::DeviceDisplayInfo info;
2022 results->depth = info.GetBitsPerPixel();
2023 results->depthPerComponent = info.GetBitsPerComponent();
2024 results->isMonochrome = (results->depthPerComponent == 0);
2027 } // namespace content