[MacViews] Show comboboxes with a native NSMenu
[chromium-blink-merge.git] / content / browser / renderer_host / render_widget_host_view_android.cc
blobe6257f2edfcb0b614ea060f9ff61bd473e5c08cc
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/devtools/render_frame_devtools_agent_host.h"
44 #include "content/browser/gpu/browser_gpu_channel_host_factory.h"
45 #include "content/browser/gpu/compositor_util.h"
46 #include "content/browser/gpu/gpu_data_manager_impl.h"
47 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
48 #include "content/browser/gpu/gpu_surface_tracker.h"
49 #include "content/browser/media/media_web_contents_observer.h"
50 #include "content/browser/renderer_host/compositor_impl_android.h"
51 #include "content/browser/renderer_host/dip_util.h"
52 #include "content/browser/renderer_host/frame_metadata_util.h"
53 #include "content/browser/renderer_host/input/synthetic_gesture_target_android.h"
54 #include "content/browser/renderer_host/input/ui_touch_selection_helper.h"
55 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
56 #include "content/browser/renderer_host/input/web_input_event_util.h"
57 #include "content/browser/renderer_host/render_process_host_impl.h"
58 #include "content/browser/renderer_host/render_view_host_impl.h"
59 #include "content/browser/renderer_host/render_widget_host_impl.h"
60 #include "content/common/gpu/client/gl_helper.h"
61 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
62 #include "content/common/gpu/gpu_messages.h"
63 #include "content/common/gpu/gpu_process_launch_causes.h"
64 #include "content/common/input/did_overscroll_params.h"
65 #include "content/common/input_messages.h"
66 #include "content/common/view_messages.h"
67 #include "content/public/browser/android/compositor.h"
68 #include "content/public/browser/browser_thread.h"
69 #include "content/public/browser/devtools_agent_host.h"
70 #include "content/public/browser/render_view_host.h"
71 #include "content/public/browser/render_widget_host_iterator.h"
72 #include "content/public/common/content_switches.h"
73 #include "gpu/command_buffer/client/gles2_implementation.h"
74 #include "gpu/command_buffer/client/gles2_interface.h"
75 #include "gpu/config/gpu_driver_bug_workaround_type.h"
76 #include "skia/ext/image_operations.h"
77 #include "third_party/khronos/GLES2/gl2.h"
78 #include "third_party/khronos/GLES2/gl2ext.h"
79 #include "third_party/skia/include/core/SkCanvas.h"
80 #include "ui/android/window_android.h"
81 #include "ui/android/window_android_compositor.h"
82 #include "ui/events/blink/blink_event_util.h"
83 #include "ui/events/gesture_detection/gesture_provider_config_helper.h"
84 #include "ui/events/gesture_detection/motion_event.h"
85 #include "ui/gfx/android/device_display_info.h"
86 #include "ui/gfx/android/java_bitmap.h"
87 #include "ui/gfx/android/view_configuration.h"
88 #include "ui/gfx/display.h"
89 #include "ui/gfx/geometry/dip_util.h"
90 #include "ui/gfx/geometry/size_conversions.h"
91 #include "ui/gfx/screen.h"
92 #include "ui/touch_selection/touch_selection_controller.h"
94 namespace content {
96 namespace {
98 void SatisfyCallback(cc::SurfaceManager* manager,
99 cc::SurfaceSequence sequence) {
100 std::vector<uint32_t> sequences;
101 sequences.push_back(sequence.sequence);
102 manager->DidSatisfySequences(sequence.id_namespace, &sequences);
105 void RequireCallback(cc::SurfaceManager* manager,
106 cc::SurfaceId id,
107 cc::SurfaceSequence sequence) {
108 cc::Surface* surface = manager->GetSurfaceForId(id);
109 if (!surface) {
110 LOG(ERROR) << "Attempting to require callback on nonexistent surface";
111 return;
113 surface->AddDestructionDependency(sequence);
116 const int kUndefinedOutputSurfaceId = -1;
118 static const char kAsyncReadBackString[] = "Compositing.CopyFromSurfaceTime";
120 class GLHelperHolder
121 : public blink::WebGraphicsContext3D::WebGraphicsContextLostCallback {
122 public:
123 static GLHelperHolder* Create();
124 ~GLHelperHolder() override;
126 void Initialize();
128 // WebGraphicsContextLostCallback implementation.
129 void onContextLost() override;
131 GLHelper* GetGLHelper() { return gl_helper_.get(); }
132 bool IsLost() { return !context_.get() || context_->isContextLost(); }
134 private:
135 GLHelperHolder();
136 static scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateContext3D();
138 scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context_;
139 scoped_ptr<GLHelper> gl_helper_;
141 DISALLOW_COPY_AND_ASSIGN(GLHelperHolder);
144 GLHelperHolder* GLHelperHolder::Create() {
145 GLHelperHolder* holder = new GLHelperHolder;
146 holder->Initialize();
148 return holder;
151 GLHelperHolder::GLHelperHolder() {
154 GLHelperHolder::~GLHelperHolder() {
157 void GLHelperHolder::Initialize() {
158 context_ = CreateContext3D();
159 if (context_) {
160 context_->setContextLostCallback(this);
161 gl_helper_.reset(new GLHelper(context_->GetImplementation(),
162 context_->GetContextSupport()));
166 void GLHelperHolder::onContextLost() {
167 // Need to post a task because the command buffer client cannot be deleted
168 // from within this callback.
169 LOG(ERROR) << "Context lost.";
170 base::MessageLoop::current()->PostTask(
171 FROM_HERE,
172 base::Bind(&RenderWidgetHostViewAndroid::OnContextLost));
175 scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
176 GLHelperHolder::CreateContext3D() {
177 BrowserGpuChannelHostFactory* factory =
178 BrowserGpuChannelHostFactory::instance();
179 scoped_refptr<GpuChannelHost> gpu_channel_host(factory->GetGpuChannel());
180 // GLHelper can only be used in asynchronous APIs for postprocessing after
181 // Browser Compositor operations (i.e. readback).
182 if (!gpu_channel_host.get()) {
183 // The Browser Compositor is in charge of reestablishing the channel.
184 return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
187 blink::WebGraphicsContext3D::Attributes attrs;
188 attrs.shareResources = true;
189 GURL url("chrome://gpu/RenderWidgetHostViewAndroid");
190 static const size_t kBytesPerPixel = 4;
191 gfx::DeviceDisplayInfo display_info;
192 size_t full_screen_texture_size_in_bytes = display_info.GetDisplayHeight() *
193 display_info.GetDisplayWidth() *
194 kBytesPerPixel;
195 WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits;
196 limits.command_buffer_size = 64 * 1024;
197 limits.start_transfer_buffer_size = 64 * 1024;
198 limits.min_transfer_buffer_size = 64 * 1024;
199 limits.max_transfer_buffer_size = std::min(
200 3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize);
201 limits.mapped_memory_reclaim_limit =
202 WebGraphicsContext3DCommandBufferImpl::kNoLimit;
203 bool lose_context_when_out_of_memory = false;
204 scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
205 new WebGraphicsContext3DCommandBufferImpl(
206 0, // offscreen
207 url, gpu_channel_host.get(), attrs, lose_context_when_out_of_memory,
208 limits, nullptr));
209 context->SetContextType(BROWSER_OFFSCREEN_MAINTHREAD_CONTEXT);
210 if (context->InitializeOnCurrentThread()) {
211 context->traceBeginCHROMIUM(
212 "gpu_toplevel",
213 base::StringPrintf("CmdBufferImageTransportFactory-%p",
214 context.get()).c_str());
215 } else {
216 context.reset();
219 return context.Pass();
222 // This can only be used for readback postprocessing. It may return null if the
223 // channel was lost and not reestablished yet.
224 GLHelper* GetPostReadbackGLHelper() {
225 static GLHelperHolder* g_readback_helper_holder = nullptr;
227 if (g_readback_helper_holder && g_readback_helper_holder->IsLost()) {
228 delete g_readback_helper_holder;
229 g_readback_helper_holder = nullptr;
232 if (!g_readback_helper_holder)
233 g_readback_helper_holder = GLHelperHolder::Create();
235 return g_readback_helper_holder->GetGLHelper();
238 void CopyFromCompositingSurfaceFinished(
239 ReadbackRequestCallback& callback,
240 scoped_ptr<cc::SingleReleaseCallback> release_callback,
241 scoped_ptr<SkBitmap> bitmap,
242 const base::TimeTicks& start_time,
243 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
244 bool result) {
245 TRACE_EVENT0(
246 "cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceFinished");
247 bitmap_pixels_lock.reset();
248 uint32 sync_point = 0;
249 if (result) {
250 GLHelper* gl_helper = GetPostReadbackGLHelper();
251 if (gl_helper)
252 sync_point = gl_helper->InsertSyncPoint();
254 bool lost_resource = sync_point == 0;
255 release_callback->Run(sync_point, lost_resource);
256 UMA_HISTOGRAM_TIMES(kAsyncReadBackString,
257 base::TimeTicks::Now() - start_time);
258 ReadbackResponse response = result ? READBACK_SUCCESS : READBACK_FAILED;
259 callback.Run(*bitmap, response);
262 scoped_ptr<ui::TouchSelectionController> CreateSelectionController(
263 ui::TouchSelectionControllerClient* client,
264 ContentViewCore* content_view_core) {
265 DCHECK(client);
266 DCHECK(content_view_core);
267 ui::TouchSelectionController::Config config;
268 config.max_tap_duration = base::TimeDelta::FromMilliseconds(
269 gfx::ViewConfiguration::GetLongPressTimeoutInMs());
270 config.tap_slop = gfx::ViewConfiguration::GetTouchSlopInDips();
271 config.show_on_tap_for_empty_editable = false;
272 config.enable_longpress_drag_selection =
273 base::CommandLine::ForCurrentProcess()->HasSwitch(
274 switches::kEnableLongpressDragSelection);
275 return make_scoped_ptr(new ui::TouchSelectionController(client, config));
278 scoped_ptr<OverscrollControllerAndroid> CreateOverscrollController(
279 ContentViewCoreImpl* content_view_core) {
280 return make_scoped_ptr(new OverscrollControllerAndroid(content_view_core));
283 gfx::RectF GetSelectionRect(const ui::TouchSelectionController& controller) {
284 gfx::RectF rect = controller.GetRectBetweenBounds();
285 if (rect.IsEmpty())
286 return rect;
288 rect.Union(controller.GetStartHandleRect());
289 rect.Union(controller.GetEndHandleRect());
290 return rect;
293 } // anonymous namespace
295 RenderWidgetHostViewAndroid::LastFrameInfo::LastFrameInfo(
296 uint32 output_id,
297 scoped_ptr<cc::CompositorFrame> output_frame)
298 : output_surface_id(output_id), frame(output_frame.Pass()) {}
300 RenderWidgetHostViewAndroid::LastFrameInfo::~LastFrameInfo() {}
302 void RenderWidgetHostViewAndroid::OnContextLost() {
303 scoped_ptr<RenderWidgetHostIterator> widgets(
304 RenderWidgetHostImpl::GetAllRenderWidgetHosts());
305 while (RenderWidgetHost* widget = widgets->GetNextHost()) {
306 if (widget->GetView()) {
307 static_cast<RenderWidgetHostViewAndroid*>(widget->GetView())
308 ->OnLostResources();
313 RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
314 RenderWidgetHostImpl* widget_host,
315 ContentViewCoreImpl* content_view_core)
316 : host_(widget_host),
317 outstanding_vsync_requests_(0),
318 is_showing_(!widget_host->is_hidden()),
319 content_view_core_(nullptr),
320 content_view_core_window_android_(nullptr),
321 ime_adapter_android_(this),
322 cached_background_color_(SK_ColorWHITE),
323 last_output_surface_id_(kUndefinedOutputSurfaceId),
324 gesture_provider_(ui::GetGestureProviderConfig(
325 ui::GestureProviderConfigType::CURRENT_PLATFORM),
326 this),
327 stylus_text_selector_(this),
328 accelerated_surface_route_id_(0),
329 using_browser_compositor_(CompositorImpl::IsInitialized()),
330 frame_evictor_(new DelegatedFrameEvictor(this)),
331 locks_on_frame_count_(0),
332 observing_root_window_(false),
333 weak_ptr_factory_(this) {
334 if (CompositorImpl::GetSurfaceManager())
335 id_allocator_ = CompositorImpl::CreateSurfaceIdAllocator();
336 host_->SetView(this);
337 SetContentViewCore(content_view_core);
340 RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() {
341 SetContentViewCore(NULL);
342 DCHECK(ack_callbacks_.empty());
343 if (resource_collection_.get())
344 resource_collection_->SetClient(NULL);
345 DCHECK(!surface_factory_);
346 DCHECK(surface_id_.is_null());
349 void RenderWidgetHostViewAndroid::Blur() {
350 host_->Blur();
351 if (overscroll_controller_)
352 overscroll_controller_->Disable();
355 bool RenderWidgetHostViewAndroid::OnMessageReceived(
356 const IPC::Message& message) {
357 bool handled = true;
358 IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAndroid, message)
359 IPC_MESSAGE_HANDLER(ViewHostMsg_StartContentIntent, OnStartContentIntent)
360 IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeBodyBackgroundColor,
361 OnDidChangeBodyBackgroundColor)
362 IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrames,
363 OnSetNeedsBeginFrames)
364 IPC_MESSAGE_HANDLER(ViewHostMsg_SmartClipDataExtracted,
365 OnSmartClipDataExtracted)
366 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowUnhandledTapUIIfNeeded,
367 OnShowUnhandledTapUIIfNeeded)
368 IPC_MESSAGE_UNHANDLED(handled = false)
369 IPC_END_MESSAGE_MAP()
370 return handled;
373 void RenderWidgetHostViewAndroid::InitAsChild(gfx::NativeView parent_view) {
374 NOTIMPLEMENTED();
377 void RenderWidgetHostViewAndroid::InitAsPopup(
378 RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) {
379 NOTIMPLEMENTED();
382 void RenderWidgetHostViewAndroid::InitAsFullscreen(
383 RenderWidgetHostView* reference_host_view) {
384 NOTIMPLEMENTED();
387 RenderWidgetHost*
388 RenderWidgetHostViewAndroid::GetRenderWidgetHost() const {
389 return host_;
392 void RenderWidgetHostViewAndroid::WasResized() {
393 host_->WasResized();
396 void RenderWidgetHostViewAndroid::SetSize(const gfx::Size& size) {
397 // Ignore the given size as only the Java code has the power to
398 // resize the view on Android.
399 default_size_ = size;
402 void RenderWidgetHostViewAndroid::SetBounds(const gfx::Rect& rect) {
403 SetSize(rect.size());
406 void RenderWidgetHostViewAndroid::GetScaledContentBitmap(
407 float scale,
408 SkColorType preferred_color_type,
409 gfx::Rect src_subrect,
410 ReadbackRequestCallback& result_callback) {
411 if (!host_ || host_->is_hidden() || !IsSurfaceAvailableForCopy()) {
412 result_callback.Run(SkBitmap(), READBACK_SURFACE_UNAVAILABLE);
413 return;
415 gfx::Size bounds = layer_->bounds();
416 if (src_subrect.IsEmpty())
417 src_subrect = gfx::Rect(bounds);
418 DCHECK_LE(src_subrect.width() + src_subrect.x(), bounds.width());
419 DCHECK_LE(src_subrect.height() + src_subrect.y(), bounds.height());
420 const gfx::Display& display =
421 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
422 float device_scale_factor = display.device_scale_factor();
423 DCHECK_GT(device_scale_factor, 0);
424 gfx::Size dst_size(gfx::ToCeiledSize(
425 gfx::ScaleSize(src_subrect.size(), scale / device_scale_factor)));
426 src_subrect = gfx::ConvertRectToDIP(device_scale_factor, src_subrect);
428 CopyFromCompositingSurface(src_subrect, dst_size, result_callback,
429 preferred_color_type);
432 scoped_refptr<cc::Layer> RenderWidgetHostViewAndroid::CreateDelegatedLayer()
433 const {
434 scoped_refptr<cc::Layer> delegated_layer;
435 if (!surface_id_.is_null()) {
436 cc::SurfaceManager* manager = CompositorImpl::GetSurfaceManager();
437 DCHECK(manager);
438 // manager must outlive compositors using it.
439 scoped_refptr<cc::SurfaceLayer> surface_layer = cc::SurfaceLayer::Create(
440 Compositor::LayerSettings(),
441 base::Bind(&SatisfyCallback, base::Unretained(manager)),
442 base::Bind(&RequireCallback, base::Unretained(manager)));
443 surface_layer->SetSurfaceId(surface_id_, 1.f, texture_size_in_layer_);
444 delegated_layer = surface_layer;
445 } else {
446 DCHECK(frame_provider_.get());
447 delegated_layer = cc::DelegatedRendererLayer::Create(
448 Compositor::LayerSettings(), frame_provider_);
450 delegated_layer->SetBounds(texture_size_in_layer_);
451 delegated_layer->SetIsDrawable(true);
452 delegated_layer->SetContentsOpaque(true);
454 return delegated_layer;
457 bool RenderWidgetHostViewAndroid::HasValidFrame() const {
458 if (!content_view_core_)
459 return false;
460 if (!layer_.get())
461 return false;
463 if (texture_size_in_layer_.IsEmpty())
464 return false;
465 // This tell us whether a valid frame has arrived or not.
466 if (!frame_evictor_->HasFrame())
467 return false;
469 return true;
472 gfx::Vector2dF RenderWidgetHostViewAndroid::GetLastScrollOffset() const {
473 return last_scroll_offset_;
476 gfx::NativeView RenderWidgetHostViewAndroid::GetNativeView() const {
477 return content_view_core_->GetViewAndroid();
480 gfx::NativeViewId RenderWidgetHostViewAndroid::GetNativeViewId() const {
481 return reinterpret_cast<gfx::NativeViewId>(
482 const_cast<RenderWidgetHostViewAndroid*>(this));
485 gfx::NativeViewAccessible
486 RenderWidgetHostViewAndroid::GetNativeViewAccessible() {
487 NOTIMPLEMENTED();
488 return NULL;
491 void RenderWidgetHostViewAndroid::MovePluginWindows(
492 const std::vector<WebPluginGeometry>& moves) {
493 // We don't have plugin windows on Android. Do nothing. Note: this is called
494 // from RenderWidgetHost::OnUpdateRect which is itself invoked while
495 // processing the corresponding message from Renderer.
498 void RenderWidgetHostViewAndroid::Focus() {
499 host_->Focus();
500 if (overscroll_controller_)
501 overscroll_controller_->Enable();
502 if (content_view_core_) {
503 WebContentsImpl* web_contents_impl =
504 static_cast<WebContentsImpl*>(content_view_core_->GetWebContents());
505 if (web_contents_impl->ShowingInterstitialPage())
506 content_view_core_->ForceUpdateImeAdapter(GetNativeImeAdapter());
510 bool RenderWidgetHostViewAndroid::HasFocus() const {
511 if (!content_view_core_)
512 return false; // ContentViewCore not created yet.
514 return content_view_core_->HasFocus();
517 bool RenderWidgetHostViewAndroid::IsSurfaceAvailableForCopy() const {
518 return HasValidFrame();
521 void RenderWidgetHostViewAndroid::Show() {
522 if (is_showing_)
523 return;
525 is_showing_ = true;
526 ShowInternal();
529 void RenderWidgetHostViewAndroid::Hide() {
530 if (!is_showing_)
531 return;
533 is_showing_ = false;
535 bool hide_frontbuffer = true;
536 bool stop_observing_root_window = true;
537 HideInternal(hide_frontbuffer, stop_observing_root_window);
540 bool RenderWidgetHostViewAndroid::IsShowing() {
541 // ContentViewCoreImpl represents the native side of the Java
542 // ContentViewCore. It being NULL means that it is not attached
543 // to the View system yet, so we treat this RWHVA as hidden.
544 return is_showing_ && content_view_core_;
547 void RenderWidgetHostViewAndroid::LockCompositingSurface() {
548 DCHECK(HasValidFrame());
549 DCHECK(host_);
550 DCHECK(frame_evictor_->HasFrame());
551 frame_evictor_->LockFrame();
552 locks_on_frame_count_++;
555 void RenderWidgetHostViewAndroid::UnlockCompositingSurface() {
556 if (!frame_evictor_->HasFrame() || locks_on_frame_count_ == 0)
557 return;
559 DCHECK(HasValidFrame());
560 frame_evictor_->UnlockFrame();
561 locks_on_frame_count_--;
563 if (locks_on_frame_count_ == 0) {
564 if (last_frame_info_) {
565 InternalSwapCompositorFrame(last_frame_info_->output_surface_id,
566 last_frame_info_->frame.Pass());
567 last_frame_info_.reset();
570 if (!is_showing_ && layer_.get())
571 layer_->SetHideLayerAndSubtree(true);
575 void RenderWidgetHostViewAndroid::SetTextSurroundingSelectionCallback(
576 const TextSurroundingSelectionCallback& callback) {
577 // Only one outstanding request is allowed at any given time.
578 DCHECK(!callback.is_null());
579 text_surrounding_selection_callback_ = callback;
582 void RenderWidgetHostViewAndroid::OnTextSurroundingSelectionResponse(
583 const base::string16& content,
584 size_t start_offset,
585 size_t end_offset) {
586 if (text_surrounding_selection_callback_.is_null())
587 return;
588 text_surrounding_selection_callback_.Run(content, start_offset, end_offset);
589 text_surrounding_selection_callback_.Reset();
592 void RenderWidgetHostViewAndroid::OnShowUnhandledTapUIIfNeeded(int x_dip,
593 int y_dip) {
594 if (!content_view_core_)
595 return;
596 // Validate the coordinates are within the viewport.
597 gfx::Size viewport_size = content_view_core_->GetViewportSizeDip();
598 if (x_dip < 0 || x_dip > viewport_size.width() ||
599 y_dip < 0 || y_dip > viewport_size.height())
600 return;
601 content_view_core_->OnShowUnhandledTapUIIfNeeded(x_dip, y_dip);
604 void RenderWidgetHostViewAndroid::ReleaseLocksOnSurface() {
605 if (!frame_evictor_->HasFrame()) {
606 DCHECK_EQ(locks_on_frame_count_, 0u);
607 return;
609 while (locks_on_frame_count_ > 0) {
610 UnlockCompositingSurface();
612 RunAckCallbacks(cc::SurfaceDrawStatus::DRAW_SKIPPED);
615 gfx::Rect RenderWidgetHostViewAndroid::GetViewBounds() const {
616 if (!content_view_core_)
617 return gfx::Rect(default_size_);
619 return gfx::Rect(content_view_core_->GetViewSize());
622 gfx::Size RenderWidgetHostViewAndroid::GetPhysicalBackingSize() const {
623 if (!content_view_core_)
624 return gfx::Size();
626 return content_view_core_->GetPhysicalBackingSize();
629 bool RenderWidgetHostViewAndroid::DoTopControlsShrinkBlinkSize() const {
630 if (!content_view_core_)
631 return false;
633 // Whether or not Blink's viewport size should be shrunk by the height of the
634 // URL-bar.
635 return content_view_core_->DoTopControlsShrinkBlinkSize();
638 float RenderWidgetHostViewAndroid::GetTopControlsHeight() const {
639 if (!content_view_core_)
640 return 0.f;
642 // The height of the top controls.
643 return content_view_core_->GetTopControlsHeightDip();
646 void RenderWidgetHostViewAndroid::UpdateCursor(const WebCursor& cursor) {
647 // There are no cursors on Android.
650 void RenderWidgetHostViewAndroid::SetIsLoading(bool is_loading) {
651 // Do nothing. The UI notification is handled through ContentViewClient which
652 // is TabContentsDelegate.
655 long RenderWidgetHostViewAndroid::GetNativeImeAdapter() {
656 return reinterpret_cast<intptr_t>(&ime_adapter_android_);
659 void RenderWidgetHostViewAndroid::TextInputStateChanged(
660 const ViewHostMsg_TextInputState_Params& params) {
661 if (params.is_non_ime_change) {
662 // Sends an acknowledgement to the renderer of a processed IME event.
663 host_->Send(new InputMsg_ImeEventAck(host_->GetRoutingID()));
666 if (!IsShowing())
667 return;
669 content_view_core_->UpdateImeAdapter(
670 GetNativeImeAdapter(),
671 static_cast<int>(params.type), params.flags,
672 params.value, params.selection_start, params.selection_end,
673 params.composition_start, params.composition_end,
674 params.show_ime_if_needed, params.is_non_ime_change);
677 void RenderWidgetHostViewAndroid::OnDidChangeBodyBackgroundColor(
678 SkColor color) {
679 if (cached_background_color_ == color)
680 return;
682 cached_background_color_ = color;
683 if (content_view_core_)
684 content_view_core_->OnBackgroundColorChanged(color);
687 void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrames(bool enabled) {
688 TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::OnSetNeedsBeginFrames",
689 "enabled", enabled);
690 if (enabled)
691 RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME);
692 else
693 outstanding_vsync_requests_ &= ~PERSISTENT_BEGIN_FRAME;
696 void RenderWidgetHostViewAndroid::OnStartContentIntent(
697 const GURL& content_url) {
698 if (content_view_core_)
699 content_view_core_->StartContentIntent(content_url);
702 void RenderWidgetHostViewAndroid::OnSmartClipDataExtracted(
703 const base::string16& text,
704 const base::string16& html,
705 const gfx::Rect rect) {
706 if (content_view_core_)
707 content_view_core_->OnSmartClipDataExtracted(text, html, rect);
710 bool RenderWidgetHostViewAndroid::OnTouchEvent(
711 const ui::MotionEvent& event) {
712 if (!host_)
713 return false;
715 // If a browser-based widget consumes the touch event, it's critical that
716 // touch event interception be disabled. This avoids issues with
717 // double-handling for embedder-detected gestures like side swipe.
718 if (selection_controller_ &&
719 selection_controller_->WillHandleTouchEvent(event)) {
720 RequestDisallowInterceptTouchEvent();
721 return true;
724 if (stylus_text_selector_.OnTouchEvent(event)) {
725 RequestDisallowInterceptTouchEvent();
726 return true;
729 ui::FilteredGestureProvider::TouchHandlingResult result =
730 gesture_provider_.OnTouchEvent(event);
731 if (!result.succeeded)
732 return false;
734 blink::WebTouchEvent web_event =
735 ui::CreateWebTouchEventFromMotionEvent(event, result.did_generate_scroll);
736 host_->ForwardTouchEventWithLatencyInfo(web_event, ui::LatencyInfo());
738 // Send a proactive BeginFrame for this vsync to reduce scroll latency for
739 // scroll-inducing touch events. Note that Android's Choreographer ensures
740 // that BeginFrame requests made during ACTION_MOVE dispatch will be honored
741 // in the same vsync phase.
742 if (observing_root_window_&& result.did_generate_scroll)
743 RequestVSyncUpdate(BEGIN_FRAME);
745 return true;
748 bool RenderWidgetHostViewAndroid::OnTouchHandleEvent(
749 const ui::MotionEvent& event) {
750 return selection_controller_ &&
751 selection_controller_->WillHandleTouchEvent(event);
754 void RenderWidgetHostViewAndroid::ResetGestureDetection() {
755 const ui::MotionEvent* current_down_event =
756 gesture_provider_.GetCurrentDownEvent();
757 if (!current_down_event) {
758 // A hard reset ensures prevention of any timer-based events that might fire
759 // after a touch sequence has ended.
760 gesture_provider_.ResetDetection();
761 return;
764 scoped_ptr<ui::MotionEvent> cancel_event = current_down_event->Cancel();
765 if (gesture_provider_.OnTouchEvent(*cancel_event).succeeded) {
766 bool causes_scrolling = false;
767 host_->ForwardTouchEventWithLatencyInfo(
768 ui::CreateWebTouchEventFromMotionEvent(*cancel_event, causes_scrolling),
769 ui::LatencyInfo());
773 void RenderWidgetHostViewAndroid::OnDidNavigateMainFrameToNewPage() {
774 ResetGestureDetection();
777 void RenderWidgetHostViewAndroid::SetDoubleTapSupportEnabled(bool enabled) {
778 gesture_provider_.SetDoubleTapSupportForPlatformEnabled(enabled);
781 void RenderWidgetHostViewAndroid::SetMultiTouchZoomSupportEnabled(
782 bool enabled) {
783 gesture_provider_.SetMultiTouchZoomSupportEnabled(enabled);
786 void RenderWidgetHostViewAndroid::ImeCancelComposition() {
787 ime_adapter_android_.CancelComposition();
790 void RenderWidgetHostViewAndroid::ImeCompositionRangeChanged(
791 const gfx::Range& range,
792 const std::vector<gfx::Rect>& character_bounds) {
793 // TODO(yukawa): Implement this.
796 void RenderWidgetHostViewAndroid::FocusedNodeChanged(bool is_editable_node) {
797 ime_adapter_android_.FocusedNodeChanged(is_editable_node);
800 void RenderWidgetHostViewAndroid::RenderProcessGone(
801 base::TerminationStatus status, int error_code) {
802 Destroy();
805 void RenderWidgetHostViewAndroid::Destroy() {
806 RemoveLayers();
807 SetContentViewCore(NULL);
809 if (!surface_id_.is_null()) {
810 DCHECK(surface_factory_.get());
811 surface_factory_->Destroy(surface_id_);
812 surface_id_ = cc::SurfaceId();
814 surface_factory_.reset();
816 // The RenderWidgetHost's destruction led here, so don't call it.
817 host_ = NULL;
819 delete this;
822 void RenderWidgetHostViewAndroid::SetTooltipText(
823 const base::string16& tooltip_text) {
824 // Tooltips don't makes sense on Android.
827 void RenderWidgetHostViewAndroid::SelectionChanged(const base::string16& text,
828 size_t offset,
829 const gfx::Range& range) {
830 RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
832 if (!content_view_core_)
833 return;
834 if (range.is_empty()) {
835 content_view_core_->OnSelectionChanged("");
836 return;
839 DCHECK(!text.empty());
840 size_t pos = range.GetMin() - offset;
841 size_t n = range.length();
843 DCHECK(pos + n <= text.length()) << "The text can not fully cover range.";
844 if (pos >= text.length()) {
845 NOTREACHED() << "The text can not cover range.";
846 return;
849 std::string utf8_selection = base::UTF16ToUTF8(text.substr(pos, n));
851 content_view_core_->OnSelectionChanged(utf8_selection);
854 void RenderWidgetHostViewAndroid::SelectionBoundsChanged(
855 const ViewHostMsg_SelectionBounds_Params& params) {
856 NOTREACHED() << "Selection bounds should be routed through the compositor.";
859 void RenderWidgetHostViewAndroid::SetBackgroundColor(SkColor color) {
860 RenderWidgetHostViewBase::SetBackgroundColor(color);
861 host_->SetBackgroundOpaque(GetBackgroundOpaque());
862 OnDidChangeBodyBackgroundColor(color);
865 void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
866 const gfx::Rect& src_subrect,
867 const gfx::Size& dst_size,
868 ReadbackRequestCallback& callback,
869 const SkColorType preferred_color_type) {
870 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurface");
871 if (!host_ || host_->is_hidden()) {
872 callback.Run(SkBitmap(), READBACK_SURFACE_UNAVAILABLE);
873 return;
875 base::TimeTicks start_time = base::TimeTicks::Now();
876 if (using_browser_compositor_ && !IsSurfaceAvailableForCopy()) {
877 callback.Run(SkBitmap(), READBACK_SURFACE_UNAVAILABLE);
878 return;
880 const gfx::Display& display =
881 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
882 float device_scale_factor = display.device_scale_factor();
883 gfx::Size dst_size_in_pixel =
884 gfx::ConvertRectToPixel(device_scale_factor, gfx::Rect(dst_size)).size();
885 gfx::Rect src_subrect_in_pixel =
886 gfx::ConvertRectToPixel(device_scale_factor, src_subrect);
888 if (!using_browser_compositor_) {
889 SynchronousCopyContents(src_subrect_in_pixel, dst_size_in_pixel, callback,
890 preferred_color_type);
891 UMA_HISTOGRAM_TIMES("Compositing.CopyFromSurfaceTimeSynchronous",
892 base::TimeTicks::Now() - start_time);
893 return;
896 scoped_ptr<cc::CopyOutputRequest> request;
897 scoped_refptr<cc::Layer> readback_layer;
898 DCHECK(content_view_core_window_android_);
899 ui::WindowAndroidCompositor* compositor =
900 content_view_core_window_android_->GetCompositor();
901 DCHECK(compositor);
902 DCHECK(frame_provider_.get() || !surface_id_.is_null());
903 scoped_refptr<cc::Layer> layer = CreateDelegatedLayer();
904 DCHECK(layer);
905 layer->SetHideLayerAndSubtree(true);
906 compositor->AttachLayerForReadback(layer);
908 readback_layer = layer;
909 request = cc::CopyOutputRequest::CreateRequest(
910 base::Bind(&RenderWidgetHostViewAndroid::
911 PrepareTextureCopyOutputResultForDelegatedReadback,
912 dst_size_in_pixel, preferred_color_type, start_time,
913 readback_layer, callback));
914 if (!src_subrect_in_pixel.IsEmpty())
915 request->set_area(src_subrect_in_pixel);
916 readback_layer->RequestCopyOfOutput(request.Pass());
919 void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame(
920 const gfx::Rect& src_subrect,
921 const scoped_refptr<media::VideoFrame>& target,
922 const base::Callback<void(bool)>& callback) {
923 NOTIMPLEMENTED();
924 callback.Run(false);
927 bool RenderWidgetHostViewAndroid::CanCopyToVideoFrame() const {
928 return false;
931 void RenderWidgetHostViewAndroid::ShowDisambiguationPopup(
932 const gfx::Rect& rect_pixels, const SkBitmap& zoomed_bitmap) {
933 if (!content_view_core_)
934 return;
936 content_view_core_->ShowDisambiguationPopup(rect_pixels, zoomed_bitmap);
939 scoped_ptr<SyntheticGestureTarget>
940 RenderWidgetHostViewAndroid::CreateSyntheticGestureTarget() {
941 return scoped_ptr<SyntheticGestureTarget>(new SyntheticGestureTargetAndroid(
942 host_, content_view_core_->CreateMotionEventSynthesizer()));
945 void RenderWidgetHostViewAndroid::SendDelegatedFrameAck(
946 uint32 output_surface_id) {
947 DCHECK(host_);
948 cc::CompositorFrameAck ack;
949 if (!surface_returned_resources_.empty())
950 ack.resources.swap(surface_returned_resources_);
951 if (resource_collection_.get())
952 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
953 host_->Send(new ViewMsg_SwapCompositorFrameAck(host_->GetRoutingID(),
954 output_surface_id, ack));
957 void RenderWidgetHostViewAndroid::SendReturnedDelegatedResources(
958 uint32 output_surface_id) {
959 DCHECK(host_);
960 cc::CompositorFrameAck ack;
961 if (!surface_returned_resources_.empty()) {
962 ack.resources.swap(surface_returned_resources_);
963 } else {
964 DCHECK(resource_collection_.get());
965 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
968 host_->Send(new ViewMsg_ReclaimCompositorResources(host_->GetRoutingID(),
969 output_surface_id, ack));
972 void RenderWidgetHostViewAndroid::UnusedResourcesAreAvailable() {
973 DCHECK(surface_id_.is_null());
974 if (ack_callbacks_.size())
975 return;
976 SendReturnedDelegatedResources(last_output_surface_id_);
979 void RenderWidgetHostViewAndroid::ReturnResources(
980 const cc::ReturnedResourceArray& resources) {
981 if (resources.empty())
982 return;
983 std::copy(resources.begin(), resources.end(),
984 std::back_inserter(surface_returned_resources_));
985 if (!ack_callbacks_.size())
986 SendReturnedDelegatedResources(last_output_surface_id_);
989 void RenderWidgetHostViewAndroid::DestroyDelegatedContent() {
990 RemoveLayers();
991 frame_provider_ = NULL;
992 if (!surface_id_.is_null()) {
993 DCHECK(surface_factory_.get());
994 surface_factory_->Destroy(surface_id_);
995 surface_id_ = cc::SurfaceId();
997 layer_ = NULL;
1000 void RenderWidgetHostViewAndroid::CheckOutputSurfaceChanged(
1001 uint32 output_surface_id) {
1002 if (output_surface_id == last_output_surface_id_)
1003 return;
1004 // Drop the cc::DelegatedFrameResourceCollection so that we will not return
1005 // any resources from the old output surface with the new output surface id.
1006 if (resource_collection_.get()) {
1007 resource_collection_->SetClient(NULL);
1008 if (resource_collection_->LoseAllResources())
1009 SendReturnedDelegatedResources(last_output_surface_id_);
1010 resource_collection_ = NULL;
1012 DestroyDelegatedContent();
1013 surface_factory_.reset();
1014 if (!surface_returned_resources_.empty())
1015 SendReturnedDelegatedResources(last_output_surface_id_);
1017 last_output_surface_id_ = output_surface_id;
1020 void RenderWidgetHostViewAndroid::SubmitCompositorFrame(
1021 scoped_ptr<cc::CompositorFrame> frame) {
1022 cc::SurfaceManager* manager = CompositorImpl::GetSurfaceManager();
1023 if (manager) {
1024 if (!surface_factory_) {
1025 surface_factory_ = make_scoped_ptr(new cc::SurfaceFactory(manager, this));
1027 if (surface_id_.is_null() ||
1028 texture_size_in_layer_ != current_surface_size_ ||
1029 location_bar_content_translation_ !=
1030 frame->metadata.location_bar_content_translation ||
1031 current_viewport_selection_ != frame->metadata.selection) {
1032 RemoveLayers();
1033 if (!surface_id_.is_null())
1034 surface_factory_->Destroy(surface_id_);
1035 surface_id_ = id_allocator_->GenerateId();
1036 surface_factory_->Create(surface_id_);
1037 layer_ = CreateDelegatedLayer();
1039 DCHECK(layer_);
1041 current_surface_size_ = texture_size_in_layer_;
1042 location_bar_content_translation_ =
1043 frame->metadata.location_bar_content_translation;
1044 current_viewport_selection_ = frame->metadata.selection;
1045 AttachLayers();
1048 cc::SurfaceFactory::DrawCallback ack_callback =
1049 base::Bind(&RenderWidgetHostViewAndroid::RunAckCallbacks,
1050 weak_ptr_factory_.GetWeakPtr());
1051 surface_factory_->SubmitCompositorFrame(surface_id_, frame.Pass(),
1052 ack_callback);
1053 } else {
1054 if (!resource_collection_.get()) {
1055 resource_collection_ = new cc::DelegatedFrameResourceCollection;
1056 resource_collection_->SetClient(this);
1058 if (!frame_provider_.get() ||
1059 texture_size_in_layer_ != frame_provider_->frame_size()) {
1060 RemoveLayers();
1061 frame_provider_ = new cc::DelegatedFrameProvider(
1062 resource_collection_.get(), frame->delegated_frame_data.Pass());
1063 layer_ = cc::DelegatedRendererLayer::Create(Compositor::LayerSettings(),
1064 frame_provider_);
1065 AttachLayers();
1066 } else {
1067 frame_provider_->SetFrameData(frame->delegated_frame_data.Pass());
1072 void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
1073 uint32 output_surface_id,
1074 scoped_ptr<cc::CompositorFrame> frame) {
1075 CheckOutputSurfaceChanged(output_surface_id);
1076 bool has_content = !texture_size_in_layer_.IsEmpty();
1078 // DelegatedRendererLayerImpl applies the inverse device_scale_factor of the
1079 // renderer frame, assuming that the browser compositor will scale
1080 // it back up to device scale. But on Android we put our browser layers in
1081 // physical pixels and set our browser CC device_scale_factor to 1, so this
1082 // suppresses the transform. This line may need to be removed when fixing
1083 // http://crbug.com/384134 or http://crbug.com/310763
1084 frame->delegated_frame_data->device_scale_factor = 1.0f;
1086 base::Closure ack_callback =
1087 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck,
1088 weak_ptr_factory_.GetWeakPtr(),
1089 output_surface_id);
1091 ack_callbacks_.push(ack_callback);
1093 if (!has_content) {
1094 DestroyDelegatedContent();
1095 } else {
1096 SubmitCompositorFrame(frame.Pass());
1099 if (layer_.get()) {
1100 layer_->SetIsDrawable(true);
1101 layer_->SetContentsOpaque(true);
1102 layer_->SetBounds(texture_size_in_layer_);
1105 if (host_->is_hidden())
1106 RunAckCallbacks(cc::SurfaceDrawStatus::DRAW_SKIPPED);
1109 void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame(
1110 uint32 output_surface_id,
1111 scoped_ptr<cc::CompositorFrame> frame) {
1112 last_scroll_offset_ = frame->metadata.root_scroll_offset;
1113 if (!frame->delegated_frame_data) {
1114 LOG(ERROR) << "Non-delegated renderer path no longer supported";
1115 return;
1118 if (locks_on_frame_count_ > 0) {
1119 DCHECK(HasValidFrame());
1120 RetainFrame(output_surface_id, frame.Pass());
1121 return;
1124 if (!CompositorImpl::GetSurfaceManager() && layer_.get() &&
1125 layer_->layer_tree_host()) {
1126 for (size_t i = 0; i < frame->metadata.latency_info.size(); i++) {
1127 scoped_ptr<cc::SwapPromise> swap_promise(
1128 new cc::LatencyInfoSwapPromise(frame->metadata.latency_info[i]));
1129 layer_->layer_tree_host()->QueueSwapPromise(swap_promise.Pass());
1133 DCHECK(!frame->delegated_frame_data->render_pass_list.empty());
1135 cc::RenderPass* root_pass =
1136 frame->delegated_frame_data->render_pass_list.back();
1137 texture_size_in_layer_ = root_pass->output_rect.size();
1139 cc::CompositorFrameMetadata metadata = frame->metadata;
1141 SwapDelegatedFrame(output_surface_id, frame.Pass());
1142 frame_evictor_->SwappedFrame(!host_->is_hidden());
1144 // As the metadata update may trigger view invalidation, always call it after
1145 // any potential compositor scheduling.
1146 OnFrameMetadataUpdated(metadata);
1149 void RenderWidgetHostViewAndroid::OnSwapCompositorFrame(
1150 uint32 output_surface_id,
1151 scoped_ptr<cc::CompositorFrame> frame) {
1152 InternalSwapCompositorFrame(output_surface_id, frame.Pass());
1155 void RenderWidgetHostViewAndroid::RetainFrame(
1156 uint32 output_surface_id,
1157 scoped_ptr<cc::CompositorFrame> frame) {
1158 DCHECK(locks_on_frame_count_);
1160 // Store the incoming frame so that it can be swapped when all the locks have
1161 // been released. If there is already a stored frame, then replace and skip
1162 // the previous one but make sure we still eventually send the ACK. Holding
1163 // the ACK also blocks the renderer when its max_frames_pending is reached.
1164 if (last_frame_info_) {
1165 base::Closure ack_callback =
1166 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck,
1167 weak_ptr_factory_.GetWeakPtr(),
1168 last_frame_info_->output_surface_id);
1170 ack_callbacks_.push(ack_callback);
1173 last_frame_info_.reset(new LastFrameInfo(output_surface_id, frame.Pass()));
1176 void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
1177 const cc::CompositorFrameMetadata& frame_metadata) {
1178 if (!content_view_core_)
1179 return;
1181 // This is a subset of OnSwapCompositorFrame() used in the synchronous
1182 // compositor flow.
1183 OnFrameMetadataUpdated(frame_metadata);
1185 // DevTools ScreenCast support for Android WebView.
1186 WebContents* web_contents = content_view_core_->GetWebContents();
1187 if (DevToolsAgentHost::HasFor(web_contents)) {
1188 scoped_refptr<DevToolsAgentHost> dtah =
1189 DevToolsAgentHost::GetOrCreateFor(web_contents);
1190 // Unblock the compositor.
1191 BrowserThread::PostTask(
1192 BrowserThread::UI, FROM_HERE,
1193 base::Bind(
1194 &RenderFrameDevToolsAgentHost::SynchronousSwapCompositorFrame,
1195 static_cast<RenderFrameDevToolsAgentHost*>(dtah.get()),
1196 frame_metadata));
1200 void RenderWidgetHostViewAndroid::SetOverlayVideoMode(bool enabled) {
1201 if (layer_.get())
1202 layer_->SetContentsOpaque(!enabled);
1205 bool RenderWidgetHostViewAndroid::SupportsAnimation() const {
1206 // The synchronous (WebView) compositor does not have a proper browser
1207 // compositor with which to drive animations.
1208 return using_browser_compositor_;
1211 void RenderWidgetHostViewAndroid::SetNeedsAnimate() {
1212 DCHECK(content_view_core_window_android_);
1213 DCHECK(using_browser_compositor_);
1214 content_view_core_window_android_->SetNeedsAnimate();
1217 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::PointF& position) {
1218 MoveCaret(gfx::Point(position.x(), position.y()));
1221 void RenderWidgetHostViewAndroid::MoveRangeSelectionExtent(
1222 const gfx::PointF& extent) {
1223 DCHECK(content_view_core_);
1224 content_view_core_->MoveRangeSelectionExtent(extent);
1227 void RenderWidgetHostViewAndroid::SelectBetweenCoordinates(
1228 const gfx::PointF& base,
1229 const gfx::PointF& extent) {
1230 DCHECK(content_view_core_);
1231 content_view_core_->SelectBetweenCoordinates(base, extent);
1234 void RenderWidgetHostViewAndroid::OnSelectionEvent(
1235 ui::SelectionEventType event) {
1236 DCHECK(content_view_core_);
1237 DCHECK(selection_controller_);
1238 // If a selection drag has started, it has taken over the active touch
1239 // sequence. Immediately cancel gesture detection and any downstream touch
1240 // listeners (e.g., web content) to communicate this transfer.
1241 if (event == ui::SELECTION_HANDLES_SHOWN)
1242 ResetGestureDetection();
1243 content_view_core_->OnSelectionEvent(
1244 event, selection_controller_->GetStartPosition(),
1245 GetSelectionRect(*selection_controller_));
1248 scoped_ptr<ui::TouchHandleDrawable>
1249 RenderWidgetHostViewAndroid::CreateDrawable() {
1250 DCHECK(content_view_core_);
1251 if (!using_browser_compositor_)
1252 return content_view_core_->CreatePopupTouchHandleDrawable();
1254 return scoped_ptr<ui::TouchHandleDrawable>(new CompositedTouchHandleDrawable(
1255 content_view_core_->GetLayer().get(),
1256 content_view_core_->GetDpiScale(),
1257 // Use the activity context (instead of the application context) to ensure
1258 // proper handle theming.
1259 content_view_core_->GetContext().obj()));
1262 void RenderWidgetHostViewAndroid::SynchronousCopyContents(
1263 const gfx::Rect& src_subrect_in_pixel,
1264 const gfx::Size& dst_size_in_pixel,
1265 ReadbackRequestCallback& callback,
1266 const SkColorType color_type) {
1267 gfx::Size input_size_in_pixel;
1268 if (src_subrect_in_pixel.IsEmpty())
1269 input_size_in_pixel = texture_size_in_layer_;
1270 else
1271 input_size_in_pixel = src_subrect_in_pixel.size();
1273 gfx::Size output_size_in_pixel;
1274 if (dst_size_in_pixel.IsEmpty())
1275 output_size_in_pixel = input_size_in_pixel;
1276 else
1277 output_size_in_pixel = dst_size_in_pixel;
1278 int output_width = output_size_in_pixel.width();
1279 int output_height = output_size_in_pixel.height();
1281 SynchronousCompositor* compositor =
1282 SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
1283 host_->GetRoutingID());
1284 if (!compositor) {
1285 callback.Run(SkBitmap(), READBACK_FAILED);
1286 return;
1289 SkBitmap bitmap;
1290 bitmap.allocPixels(SkImageInfo::Make(output_width,
1291 output_height,
1292 color_type,
1293 kPremul_SkAlphaType));
1294 SkCanvas canvas(bitmap);
1295 canvas.scale(
1296 (float)output_width / (float)input_size_in_pixel.width(),
1297 (float)output_height / (float)input_size_in_pixel.height());
1298 compositor->DemandDrawSw(&canvas);
1299 callback.Run(bitmap, READBACK_SUCCESS);
1302 void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
1303 const cc::CompositorFrameMetadata& frame_metadata) {
1304 bool is_mobile_optimized = IsMobileOptimizedFrame(frame_metadata);
1305 gesture_provider_.SetDoubleTapSupportForPageEnabled(!is_mobile_optimized);
1307 if (!content_view_core_)
1308 return;
1310 if (overscroll_controller_)
1311 overscroll_controller_->OnFrameMetadataUpdated(frame_metadata);
1313 if (selection_controller_) {
1314 selection_controller_->OnSelectionEditable(
1315 frame_metadata.selection.is_editable);
1316 selection_controller_->OnSelectionEmpty(
1317 frame_metadata.selection.is_empty_text_form_control);
1318 selection_controller_->OnSelectionBoundsChanged(
1319 ConvertSelectionBound(frame_metadata.selection.start),
1320 ConvertSelectionBound(frame_metadata.selection.end));
1323 // All offsets and sizes are in CSS pixels.
1324 content_view_core_->UpdateFrameInfo(
1325 frame_metadata.root_scroll_offset,
1326 frame_metadata.page_scale_factor,
1327 gfx::Vector2dF(frame_metadata.min_page_scale_factor,
1328 frame_metadata.max_page_scale_factor),
1329 frame_metadata.root_layer_size,
1330 frame_metadata.scrollable_viewport_size,
1331 frame_metadata.location_bar_offset,
1332 frame_metadata.location_bar_content_translation,
1333 is_mobile_optimized);
1334 #if defined(VIDEO_HOLE)
1335 if (host_ && host_->IsRenderView()) {
1336 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
1337 RenderViewHost::From(host_));
1338 WebContentsImpl* web_contents_impl =
1339 static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(rvhi));
1340 if (web_contents_impl)
1341 web_contents_impl->media_web_contents_observer()->OnFrameInfoUpdated();
1343 #endif // defined(VIDEO_HOLE)
1346 void RenderWidgetHostViewAndroid::AcceleratedSurfaceInitialized(int route_id) {
1347 // TODO: remove need for the surface id here
1348 accelerated_surface_route_id_ = route_id;
1351 void RenderWidgetHostViewAndroid::ShowInternal() {
1352 DCHECK(is_showing_);
1353 if (!host_ || !host_->is_hidden())
1354 return;
1356 if (layer_.get())
1357 layer_->SetHideLayerAndSubtree(false);
1359 frame_evictor_->SetVisible(true);
1361 if (overscroll_controller_)
1362 overscroll_controller_->Enable();
1364 host_->WasShown(ui::LatencyInfo());
1366 if (content_view_core_) {
1367 StartObservingRootWindow();
1368 RequestVSyncUpdate(BEGIN_FRAME);
1372 void RenderWidgetHostViewAndroid::HideInternal(
1373 bool hide_frontbuffer,
1374 bool stop_observing_root_window) {
1375 if (hide_frontbuffer) {
1376 if (layer_.get() && locks_on_frame_count_ == 0)
1377 layer_->SetHideLayerAndSubtree(true);
1379 frame_evictor_->SetVisible(false);
1382 if (stop_observing_root_window)
1383 StopObservingRootWindow();
1385 if (!host_ || host_->is_hidden())
1386 return;
1388 if (overscroll_controller_)
1389 overscroll_controller_->Disable();
1391 RunAckCallbacks(cc::SurfaceDrawStatus::DRAW_SKIPPED);
1393 // Inform the renderer that we are being hidden so it can reduce its resource
1394 // utilization.
1395 host_->WasHidden();
1398 void RenderWidgetHostViewAndroid::AttachLayers() {
1399 if (!content_view_core_)
1400 return;
1401 if (!layer_.get())
1402 return;
1404 content_view_core_->AttachLayer(layer_);
1405 layer_->SetHideLayerAndSubtree(!is_showing_);
1408 void RenderWidgetHostViewAndroid::RemoveLayers() {
1409 if (!content_view_core_)
1410 return;
1412 if (!layer_.get())
1413 return;
1415 content_view_core_->RemoveLayer(layer_);
1418 void RenderWidgetHostViewAndroid::RequestVSyncUpdate(uint32 requests) {
1419 bool should_request_vsync = !outstanding_vsync_requests_ && requests;
1420 outstanding_vsync_requests_ |= requests;
1422 // If the host has been hidden, defer vsync requests until it is shown
1423 // again via |Show()|.
1424 if (!host_ || host_->is_hidden())
1425 return;
1427 // Note that if we're not currently observing the root window, outstanding
1428 // vsync requests will be pushed if/when we resume observing in
1429 // |StartObservingRootWindow()|.
1430 if (observing_root_window_ && should_request_vsync)
1431 content_view_core_window_android_->RequestVSyncUpdate();
1434 void RenderWidgetHostViewAndroid::StartObservingRootWindow() {
1435 DCHECK(content_view_core_window_android_);
1436 DCHECK(is_showing_);
1437 if (observing_root_window_)
1438 return;
1440 observing_root_window_ = true;
1441 content_view_core_window_android_->AddObserver(this);
1443 // Clear existing vsync requests to allow a request to the new window.
1444 uint32 outstanding_vsync_requests = outstanding_vsync_requests_;
1445 outstanding_vsync_requests_ = 0;
1446 RequestVSyncUpdate(outstanding_vsync_requests);
1449 void RenderWidgetHostViewAndroid::StopObservingRootWindow() {
1450 if (!content_view_core_window_android_) {
1451 DCHECK(!observing_root_window_);
1452 return;
1455 if (!observing_root_window_)
1456 return;
1458 observing_root_window_ = false;
1459 content_view_core_window_android_->RemoveObserver(this);
1462 void RenderWidgetHostViewAndroid::SendBeginFrame(base::TimeTicks frame_time,
1463 base::TimeDelta vsync_period) {
1464 TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::SendBeginFrame",
1465 "frame_time_us", frame_time.ToInternalValue());
1467 if (using_browser_compositor_) {
1468 // TODO(brianderson): Replace this hardcoded deadline after Android
1469 // switches to Surfaces and the Browser's commit isn't in the critcal path.
1470 base::TimeTicks deadline = frame_time + (vsync_period * 0.6);
1472 host_->Send(new ViewMsg_BeginFrame(
1473 host_->GetRoutingID(),
1474 cc::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline,
1475 vsync_period, cc::BeginFrameArgs::NORMAL)));
1476 } else {
1477 SynchronousCompositorImpl* compositor = SynchronousCompositorImpl::FromID(
1478 host_->GetProcess()->GetID(), host_->GetRoutingID());
1479 if (compositor) {
1480 // The synchronous compositor synchronously does it's work in this call.
1481 // It does not use a deadline.
1482 compositor->BeginFrame(cc::BeginFrameArgs::Create(
1483 BEGINFRAME_FROM_HERE, frame_time, base::TimeTicks(), vsync_period,
1484 cc::BeginFrameArgs::NORMAL));
1489 bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) {
1490 bool needs_animate = false;
1491 if (overscroll_controller_) {
1492 needs_animate |= overscroll_controller_->Animate(
1493 frame_time, content_view_core_->GetLayer().get());
1495 if (selection_controller_)
1496 needs_animate |= selection_controller_->Animate(frame_time);
1497 return needs_animate;
1500 void RenderWidgetHostViewAndroid::RequestDisallowInterceptTouchEvent() {
1501 if (content_view_core_)
1502 content_view_core_->RequestDisallowInterceptTouchEvent();
1505 void RenderWidgetHostViewAndroid::EvictDelegatedFrame() {
1506 if (layer_.get())
1507 DestroyDelegatedContent();
1508 frame_evictor_->DiscardedFrame();
1511 bool RenderWidgetHostViewAndroid::HasAcceleratedSurface(
1512 const gfx::Size& desired_size) {
1513 NOTREACHED();
1514 return false;
1517 void RenderWidgetHostViewAndroid::GetScreenInfo(blink::WebScreenInfo* result) {
1518 // ScreenInfo isn't tied to the widget on Android. Always return the default.
1519 RenderWidgetHostViewBase::GetDefaultScreenInfo(result);
1522 bool RenderWidgetHostViewAndroid::GetScreenColorProfile(
1523 std::vector<char>* color_profile) {
1524 DCHECK(color_profile->empty());
1525 NOTREACHED();
1526 return false;
1529 // TODO(jrg): Find out the implications and answer correctly here,
1530 // as we are returning the WebView and not root window bounds.
1531 gfx::Rect RenderWidgetHostViewAndroid::GetBoundsInRootWindow() {
1532 return GetViewBounds();
1535 gfx::GLSurfaceHandle RenderWidgetHostViewAndroid::GetCompositingSurface() {
1536 gfx::GLSurfaceHandle handle =
1537 gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NULL_TRANSPORT);
1538 // Null check for when we're running inside content_unittests.
1539 if (using_browser_compositor_ && BrowserGpuChannelHostFactory::instance()) {
1540 handle.parent_client_id =
1541 BrowserGpuChannelHostFactory::instance()->GetGpuChannelId();
1543 return handle;
1546 void RenderWidgetHostViewAndroid::ProcessAckedTouchEvent(
1547 const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
1548 const bool event_consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
1549 gesture_provider_.OnTouchEventAck(touch.event.uniqueTouchEventId,
1550 event_consumed);
1553 void RenderWidgetHostViewAndroid::GestureEventAck(
1554 const blink::WebGestureEvent& event,
1555 InputEventAckState ack_result) {
1556 if (overscroll_controller_)
1557 overscroll_controller_->OnGestureEventAck(event, ack_result);
1559 if (content_view_core_)
1560 content_view_core_->OnGestureEventAck(event, ack_result);
1563 InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
1564 const blink::WebInputEvent& input_event) {
1565 if (selection_controller_ &&
1566 blink::WebInputEvent::isGestureEventType(input_event.type)) {
1567 const blink::WebGestureEvent& gesture_event =
1568 static_cast<const blink::WebGestureEvent&>(input_event);
1569 switch (gesture_event.type) {
1570 case blink::WebInputEvent::GestureLongPress:
1571 if (selection_controller_->WillHandleLongPressEvent(
1572 base::TimeTicks() +
1573 base::TimeDelta::FromSecondsD(input_event.timeStampSeconds),
1574 gfx::PointF(gesture_event.x, gesture_event.y))) {
1575 return INPUT_EVENT_ACK_STATE_CONSUMED;
1577 break;
1579 case blink::WebInputEvent::GestureTap:
1580 if (selection_controller_->WillHandleTapEvent(
1581 gfx::PointF(gesture_event.x, gesture_event.y))) {
1582 return INPUT_EVENT_ACK_STATE_CONSUMED;
1584 break;
1586 default:
1587 break;
1591 if (overscroll_controller_ &&
1592 blink::WebInputEvent::isGestureEventType(input_event.type) &&
1593 overscroll_controller_->WillHandleGestureEvent(
1594 static_cast<const blink::WebGestureEvent&>(input_event))) {
1595 return INPUT_EVENT_ACK_STATE_CONSUMED;
1598 if (content_view_core_ && content_view_core_->FilterInputEvent(input_event))
1599 return INPUT_EVENT_ACK_STATE_CONSUMED;
1601 if (!host_)
1602 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1604 if (input_event.type == blink::WebInputEvent::GestureTapDown ||
1605 input_event.type == blink::WebInputEvent::TouchStart) {
1606 GpuDataManagerImpl* gpu_data = GpuDataManagerImpl::GetInstance();
1607 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance();
1608 if (shim && gpu_data && accelerated_surface_route_id_ &&
1609 gpu_data->IsDriverBugWorkaroundActive(gpu::WAKE_UP_GPU_BEFORE_DRAWING))
1610 shim->Send(
1611 new AcceleratedSurfaceMsg_WakeUpGpu(accelerated_surface_route_id_));
1614 SynchronousCompositorImpl* compositor =
1615 SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
1616 host_->GetRoutingID());
1617 if (compositor)
1618 return compositor->HandleInputEvent(input_event);
1619 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1622 void RenderWidgetHostViewAndroid::OnSetNeedsFlushInput() {
1623 TRACE_EVENT0("input", "RenderWidgetHostViewAndroid::OnSetNeedsFlushInput");
1624 RequestVSyncUpdate(FLUSH_INPUT);
1627 BrowserAccessibilityManager*
1628 RenderWidgetHostViewAndroid::CreateBrowserAccessibilityManager(
1629 BrowserAccessibilityDelegate* delegate) {
1630 // TODO(dmazzoni): Currently there can only be one
1631 // BrowserAccessibilityManager per ContentViewCore, so return NULL
1632 // if there's already a BrowserAccessibilityManager for the main
1633 // frame. Eventually, in order to support cross-process iframes on
1634 // Android we'll need to add support for a
1635 // BrowserAccessibilityManager for a child frame.
1636 // http://crbug.com/423846
1637 if (!host_ || host_->GetRootBrowserAccessibilityManager())
1638 return NULL;
1640 base::android::ScopedJavaLocalRef<jobject> obj;
1641 if (content_view_core_)
1642 obj = content_view_core_->GetJavaObject();
1643 return new BrowserAccessibilityManagerAndroid(
1644 obj,
1645 BrowserAccessibilityManagerAndroid::GetEmptyDocument(),
1646 delegate);
1649 bool RenderWidgetHostViewAndroid::LockMouse() {
1650 NOTIMPLEMENTED();
1651 return false;
1654 void RenderWidgetHostViewAndroid::UnlockMouse() {
1655 NOTIMPLEMENTED();
1658 // Methods called from the host to the render
1660 void RenderWidgetHostViewAndroid::SendKeyEvent(
1661 const NativeWebKeyboardEvent& event) {
1662 if (host_)
1663 host_->ForwardKeyboardEvent(event);
1666 void RenderWidgetHostViewAndroid::SendMouseEvent(
1667 const blink::WebMouseEvent& event) {
1668 if (host_)
1669 host_->ForwardMouseEvent(event);
1672 void RenderWidgetHostViewAndroid::SendMouseWheelEvent(
1673 const blink::WebMouseWheelEvent& event) {
1674 if (host_)
1675 host_->ForwardWheelEvent(event);
1678 void RenderWidgetHostViewAndroid::SendGestureEvent(
1679 const blink::WebGestureEvent& event) {
1680 // Sending a gesture that may trigger overscroll should resume the effect.
1681 if (overscroll_controller_)
1682 overscroll_controller_->Enable();
1684 if (host_)
1685 host_->ForwardGestureEventWithLatencyInfo(event, ui::LatencyInfo());
1688 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point& point) {
1689 if (host_)
1690 host_->MoveCaret(point);
1693 void RenderWidgetHostViewAndroid::DismissTextHandles() {
1694 if (selection_controller_)
1695 selection_controller_->HideAndDisallowShowingAutomatically();
1698 void RenderWidgetHostViewAndroid::SetTextHandlesTemporarilyHidden(bool hidden) {
1699 if (selection_controller_)
1700 selection_controller_->SetTemporarilyHidden(hidden);
1703 void RenderWidgetHostViewAndroid::OnShowingPastePopup(
1704 const gfx::PointF& point) {
1705 if (!selection_controller_)
1706 return;
1708 // As the paste popup may be triggered *before* the bounds and editability
1709 // of the region have been updated, explicitly set the properties now.
1710 // TODO(jdduke): Remove this workaround when auxiliary paste popup
1711 // notifications are no longer required, crbug.com/398170.
1712 ui::SelectionBound insertion_bound;
1713 insertion_bound.set_type(ui::SelectionBound::CENTER);
1714 insertion_bound.set_visible(true);
1715 insertion_bound.SetEdge(point, point);
1716 selection_controller_->HideAndDisallowShowingAutomatically();
1717 selection_controller_->OnSelectionEditable(true);
1718 selection_controller_->OnSelectionEmpty(true);
1719 selection_controller_->OnSelectionBoundsChanged(insertion_bound,
1720 insertion_bound);
1721 selection_controller_->AllowShowingFromCurrentSelection();
1724 SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const {
1725 return cached_background_color_;
1728 void RenderWidgetHostViewAndroid::DidOverscroll(
1729 const DidOverscrollParams& params) {
1730 if (!content_view_core_ || !layer_.get() || !is_showing_)
1731 return;
1733 if (overscroll_controller_)
1734 overscroll_controller_->OnOverscrolled(params);
1737 void RenderWidgetHostViewAndroid::DidStopFlinging() {
1738 if (content_view_core_)
1739 content_view_core_->DidStopFlinging();
1742 uint32_t RenderWidgetHostViewAndroid::GetSurfaceIdNamespace() {
1743 if (id_allocator_)
1744 return id_allocator_->id_namespace();
1745 return 0;
1748 void RenderWidgetHostViewAndroid::SetContentViewCore(
1749 ContentViewCoreImpl* content_view_core) {
1750 RemoveLayers();
1751 StopObservingRootWindow();
1753 bool resize = false;
1754 if (content_view_core != content_view_core_) {
1755 overscroll_controller_.reset();
1756 selection_controller_.reset();
1757 ReleaseLocksOnSurface();
1758 resize = true;
1761 content_view_core_ = content_view_core;
1762 content_view_core_window_android_ =
1763 content_view_core_ ? content_view_core_->GetWindowAndroid() : nullptr;
1764 DCHECK_EQ(!!content_view_core_, !!content_view_core_window_android_);
1766 BrowserAccessibilityManager* manager = NULL;
1767 if (host_)
1768 manager = host_->GetRootBrowserAccessibilityManager();
1769 if (manager) {
1770 base::android::ScopedJavaLocalRef<jobject> obj;
1771 if (content_view_core_)
1772 obj = content_view_core_->GetJavaObject();
1773 manager->ToBrowserAccessibilityManagerAndroid()->SetContentViewCore(obj);
1776 AttachLayers();
1778 if (!content_view_core_)
1779 return;
1781 if (is_showing_)
1782 StartObservingRootWindow();
1784 if (resize)
1785 WasResized();
1787 if (!selection_controller_)
1788 selection_controller_ = CreateSelectionController(this, content_view_core_);
1790 if (!overscroll_controller_ &&
1791 content_view_core_window_android_->GetCompositor()) {
1792 overscroll_controller_ = CreateOverscrollController(content_view_core_);
1796 void RenderWidgetHostViewAndroid::RunAckCallbacks(
1797 cc::SurfaceDrawStatus status) {
1798 while (!ack_callbacks_.empty()) {
1799 ack_callbacks_.front().Run();
1800 ack_callbacks_.pop();
1804 void RenderWidgetHostViewAndroid::OnGestureEvent(
1805 const ui::GestureEventData& gesture) {
1806 blink::WebGestureEvent web_gesture =
1807 ui::CreateWebGestureEventFromGestureEventData(gesture);
1808 // TODO(jdduke): Remove this workaround after Android fixes UiAutomator to
1809 // stop providing shift meta values to synthetic MotionEvents. This prevents
1810 // unintended shift+click interpretation of all accessibility clicks.
1811 // See crbug.com/443247.
1812 if (web_gesture.type == blink::WebInputEvent::GestureTap &&
1813 web_gesture.modifiers == blink::WebInputEvent::ShiftKey) {
1814 web_gesture.modifiers = 0;
1816 SendGestureEvent(web_gesture);
1819 void RenderWidgetHostViewAndroid::OnCompositingDidCommit() {
1820 RunAckCallbacks(cc::SurfaceDrawStatus::DRAWN);
1823 void RenderWidgetHostViewAndroid::OnRootWindowVisibilityChanged(bool visible) {
1824 DCHECK(is_showing_);
1825 if (visible) {
1826 ShowInternal();
1827 } else {
1828 bool hide_frontbuffer = true;
1829 bool stop_observing_root_window = false;
1830 HideInternal(hide_frontbuffer, stop_observing_root_window);
1834 void RenderWidgetHostViewAndroid::OnAttachCompositor() {
1835 DCHECK(content_view_core_);
1836 if (!overscroll_controller_)
1837 overscroll_controller_ = CreateOverscrollController(content_view_core_);
1840 void RenderWidgetHostViewAndroid::OnDetachCompositor() {
1841 DCHECK(content_view_core_);
1842 DCHECK(using_browser_compositor_);
1843 RunAckCallbacks(cc::SurfaceDrawStatus::DRAW_SKIPPED);
1844 overscroll_controller_.reset();
1847 void RenderWidgetHostViewAndroid::OnVSync(base::TimeTicks frame_time,
1848 base::TimeDelta vsync_period) {
1849 TRACE_EVENT0("cc,benchmark", "RenderWidgetHostViewAndroid::OnVSync");
1850 if (!host_ || host_->is_hidden())
1851 return;
1853 if (outstanding_vsync_requests_ & FLUSH_INPUT) {
1854 outstanding_vsync_requests_ &= ~FLUSH_INPUT;
1855 host_->FlushInput();
1858 if (outstanding_vsync_requests_ & BEGIN_FRAME ||
1859 outstanding_vsync_requests_ & PERSISTENT_BEGIN_FRAME) {
1860 outstanding_vsync_requests_ &= ~BEGIN_FRAME;
1861 SendBeginFrame(frame_time, vsync_period);
1864 // This allows for SendBeginFrame and FlushInput to modify
1865 // outstanding_vsync_requests.
1866 uint32 outstanding_vsync_requests = outstanding_vsync_requests_;
1867 outstanding_vsync_requests_ = 0;
1868 RequestVSyncUpdate(outstanding_vsync_requests);
1871 void RenderWidgetHostViewAndroid::OnAnimate(base::TimeTicks begin_frame_time) {
1872 if (Animate(begin_frame_time))
1873 SetNeedsAnimate();
1876 void RenderWidgetHostViewAndroid::OnActivityStopped() {
1877 TRACE_EVENT0("browser", "RenderWidgetHostViewAndroid::OnActivityStopped");
1878 DCHECK(is_showing_);
1879 bool hide_frontbuffer = false;
1880 bool stop_observing_root_window = false;
1881 HideInternal(hide_frontbuffer, stop_observing_root_window);
1884 void RenderWidgetHostViewAndroid::OnActivityStarted() {
1885 TRACE_EVENT0("browser", "RenderWidgetHostViewAndroid::OnActivityStarted");
1886 DCHECK(is_showing_);
1887 ShowInternal();
1890 void RenderWidgetHostViewAndroid::OnLostResources() {
1891 ReleaseLocksOnSurface();
1892 if (layer_.get())
1893 DestroyDelegatedContent();
1894 DCHECK(ack_callbacks_.empty());
1897 // static
1898 void RenderWidgetHostViewAndroid::
1899 PrepareTextureCopyOutputResultForDelegatedReadback(
1900 const gfx::Size& dst_size_in_pixel,
1901 SkColorType color_type,
1902 const base::TimeTicks& start_time,
1903 scoped_refptr<cc::Layer> readback_layer,
1904 ReadbackRequestCallback& callback,
1905 scoped_ptr<cc::CopyOutputResult> result) {
1906 readback_layer->RemoveFromParent();
1907 PrepareTextureCopyOutputResult(
1908 dst_size_in_pixel, color_type, start_time, callback, result.Pass());
1911 // static
1912 void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
1913 const gfx::Size& dst_size_in_pixel,
1914 SkColorType color_type,
1915 const base::TimeTicks& start_time,
1916 ReadbackRequestCallback& callback,
1917 scoped_ptr<cc::CopyOutputResult> result) {
1918 base::ScopedClosureRunner scoped_callback_runner(
1919 base::Bind(callback, SkBitmap(), READBACK_FAILED));
1920 TRACE_EVENT0("cc",
1921 "RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult");
1923 if (!result->HasTexture() || result->IsEmpty() || result->size().IsEmpty())
1924 return;
1926 gfx::Size output_size_in_pixel;
1927 if (dst_size_in_pixel.IsEmpty())
1928 output_size_in_pixel = result->size();
1929 else
1930 output_size_in_pixel = dst_size_in_pixel;
1932 GLHelper* gl_helper = GetPostReadbackGLHelper();
1933 if (!gl_helper)
1934 return;
1935 if (!gl_helper->IsReadbackConfigSupported(color_type))
1936 color_type = kRGBA_8888_SkColorType;
1937 scoped_ptr<SkBitmap> bitmap(new SkBitmap);
1938 if (!bitmap->tryAllocPixels(SkImageInfo::Make(output_size_in_pixel.width(),
1939 output_size_in_pixel.height(),
1940 color_type,
1941 kOpaque_SkAlphaType))) {
1942 scoped_callback_runner.Reset(
1943 base::Bind(callback, SkBitmap(), READBACK_BITMAP_ALLOCATION_FAILURE));
1944 return;
1948 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock(
1949 new SkAutoLockPixels(*bitmap));
1950 uint8* pixels = static_cast<uint8*>(bitmap->getPixels());
1952 cc::TextureMailbox texture_mailbox;
1953 scoped_ptr<cc::SingleReleaseCallback> release_callback;
1954 result->TakeTexture(&texture_mailbox, &release_callback);
1955 DCHECK(texture_mailbox.IsTexture());
1956 if (!texture_mailbox.IsTexture())
1957 return;
1959 ignore_result(scoped_callback_runner.Release());
1961 gl_helper->CropScaleReadbackAndCleanMailbox(
1962 texture_mailbox.mailbox(),
1963 texture_mailbox.sync_point(),
1964 result->size(),
1965 gfx::Rect(result->size()),
1966 output_size_in_pixel,
1967 pixels,
1968 color_type,
1969 base::Bind(&CopyFromCompositingSurfaceFinished,
1970 callback,
1971 base::Passed(&release_callback),
1972 base::Passed(&bitmap),
1973 start_time,
1974 base::Passed(&bitmap_pixels_lock)),
1975 GLHelper::SCALER_QUALITY_GOOD);
1978 void RenderWidgetHostViewAndroid::OnStylusSelectBegin(float x0,
1979 float y0,
1980 float x1,
1981 float y1) {
1982 SelectBetweenCoordinates(gfx::PointF(x0, y0), gfx::PointF(x1, y1));
1985 void RenderWidgetHostViewAndroid::OnStylusSelectUpdate(float x, float y) {
1986 MoveRangeSelectionExtent(gfx::PointF(x, y));
1989 void RenderWidgetHostViewAndroid::OnStylusSelectEnd() {
1990 if (selection_controller_)
1991 selection_controller_->AllowShowingFromCurrentSelection();
1994 void RenderWidgetHostViewAndroid::OnStylusSelectTap(base::TimeTicks time,
1995 float x,
1996 float y) {
1997 // Treat the stylus tap as a long press, activating either a word selection or
1998 // context menu depending on the targetted content.
1999 blink::WebGestureEvent long_press = WebGestureEventBuilder::Build(
2000 blink::WebInputEvent::GestureLongPress,
2001 (time - base::TimeTicks()).InSecondsF(), x, y);
2002 SendGestureEvent(long_press);
2005 // static
2006 void RenderWidgetHostViewBase::GetDefaultScreenInfo(
2007 blink::WebScreenInfo* results) {
2008 const gfx::Display& display =
2009 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
2010 results->rect = display.bounds();
2011 // TODO(husky): Remove any system controls from availableRect.
2012 results->availableRect = display.work_area();
2013 results->deviceScaleFactor = display.device_scale_factor();
2014 results->orientationAngle = display.RotationAsDegree();
2015 results->orientationType =
2016 RenderWidgetHostViewBase::GetOrientationTypeForMobile(display);
2017 gfx::DeviceDisplayInfo info;
2018 results->depth = info.GetBitsPerPixel();
2019 results->depthPerComponent = info.GetBitsPerComponent();
2020 results->isMonochrome = (results->depthPerComponent == 0);
2023 } // namespace content