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/basictypes.h"
10 #include "base/bind.h"
11 #include "base/callback_helpers.h"
12 #include "base/command_line.h"
13 #include "base/logging.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/threading/worker_pool.h"
17 #include "cc/layers/delegated_frame_provider.h"
18 #include "cc/layers/delegated_renderer_layer.h"
19 #include "cc/layers/layer.h"
20 #include "cc/layers/texture_layer.h"
21 #include "cc/output/compositor_frame.h"
22 #include "cc/output/compositor_frame_ack.h"
23 #include "cc/output/copy_output_request.h"
24 #include "cc/output/copy_output_result.h"
25 #include "cc/resources/single_release_callback.h"
26 #include "cc/trees/layer_tree_host.h"
27 #include "content/browser/accessibility/browser_accessibility_manager_android.h"
28 #include "content/browser/android/content_view_core_impl.h"
29 #include "content/browser/android/in_process/synchronous_compositor_impl.h"
30 #include "content/browser/android/overscroll_glow.h"
31 #include "content/browser/gpu/gpu_surface_tracker.h"
32 #include "content/browser/renderer_host/compositor_impl_android.h"
33 #include "content/browser/renderer_host/dip_util.h"
34 #include "content/browser/renderer_host/generic_touch_gesture_android.h"
35 #include "content/browser/renderer_host/image_transport_factory_android.h"
36 #include "content/browser/renderer_host/render_widget_host_impl.h"
37 #include "content/common/gpu/client/gl_helper.h"
38 #include "content/common/gpu/gpu_messages.h"
39 #include "content/common/input_messages.h"
40 #include "content/common/view_messages.h"
41 #include "content/public/common/content_switches.h"
42 #include "skia/ext/image_operations.h"
43 #include "third_party/khronos/GLES2/gl2.h"
44 #include "third_party/khronos/GLES2/gl2ext.h"
45 #include "ui/gfx/android/device_display_info.h"
46 #include "ui/gfx/android/java_bitmap.h"
47 #include "ui/gfx/display.h"
48 #include "ui/gfx/screen.h"
49 #include "ui/gfx/size_conversions.h"
55 const int kUndefinedOutputSurfaceId = -1;
56 const int kMinimumPointerDistance = 50;
58 void InsertSyncPointAndAckForGpu(
59 int gpu_host_id, int route_id, const std::string& return_mailbox) {
61 ImageTransportFactoryAndroid::GetInstance()->InsertSyncPoint();
62 AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
63 ack_params.mailbox_name = return_mailbox;
64 ack_params.sync_point = sync_point;
65 RenderWidgetHostImpl::AcknowledgeBufferPresent(
66 route_id, gpu_host_id, ack_params);
69 void InsertSyncPointAndAckForCompositor(
71 uint32 output_surface_id,
73 const gpu::Mailbox& return_mailbox,
74 const gfx::Size return_size) {
75 cc::CompositorFrameAck ack;
76 ack.gl_frame_data.reset(new cc::GLFrameData());
77 if (!return_mailbox.IsZero()) {
78 ack.gl_frame_data->mailbox = return_mailbox;
79 ack.gl_frame_data->size = return_size;
80 ack.gl_frame_data->sync_point =
81 ImageTransportFactoryAndroid::GetInstance()->InsertSyncPoint();
83 RenderWidgetHostImpl::SendSwapCompositorFrameAck(
84 route_id, output_surface_id, renderer_host_id, ack);
87 // Sends an acknowledgement to the renderer of a processed IME event.
88 void SendImeEventAck(RenderWidgetHostImpl* host) {
89 host->Send(new ViewMsg_ImeEventAck(host->GetRoutingID()));
92 void CopyFromCompositingSurfaceFinished(
93 const base::Callback<void(bool, const SkBitmap&)>& callback,
94 scoped_ptr<cc::SingleReleaseCallback> release_callback,
95 scoped_ptr<SkBitmap> bitmap,
96 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
98 bitmap_pixels_lock.reset();
99 release_callback->Run(0, false);
100 callback.Run(result, *bitmap);
103 bool UsingDelegatedRenderer() {
104 return CommandLine::ForCurrentProcess()->HasSwitch(
105 switches::kEnableDelegatedRenderer);
108 } // anonymous namespace
110 RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
111 RenderWidgetHostImpl* widget_host,
112 ContentViewCoreImpl* content_view_core)
113 : host_(widget_host),
114 needs_begin_frame_(false),
115 are_layers_attached_(true),
116 content_view_core_(NULL),
117 ime_adapter_android_(this),
118 cached_background_color_(SK_ColorWHITE),
119 texture_id_in_layer_(0),
120 last_output_surface_id_(kUndefinedOutputSurfaceId),
121 weak_ptr_factory_(this),
122 overscroll_effect_enabled_(true),
123 flush_input_requested_(false) {
124 if (!UsingDelegatedRenderer()) {
125 texture_layer_ = cc::TextureLayer::Create(this);
126 layer_ = texture_layer_;
129 overscroll_effect_enabled_ = !CommandLine::ForCurrentProcess()->
130 HasSwitch(switches::kDisableOverscrollEdgeEffect);
131 // Don't block the main thread with effect resource loading.
132 // Actual effect creation is deferred until an overscroll event is received.
133 if (overscroll_effect_enabled_) {
134 base::WorkerPool::PostTask(FROM_HERE,
135 base::Bind(&OverscrollGlow::EnsureResources),
139 host_->SetView(this);
140 SetContentViewCore(content_view_core);
141 ImageTransportFactoryAndroid::AddObserver(this);
144 RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() {
145 ImageTransportFactoryAndroid::RemoveObserver(this);
146 SetContentViewCore(NULL);
147 DCHECK(ack_callbacks_.empty());
148 if (texture_id_in_layer_) {
149 ImageTransportFactoryAndroid::GetInstance()->DeleteTexture(
150 texture_id_in_layer_);
153 if (texture_layer_.get())
154 texture_layer_->ClearClient();
156 if (resource_collection_.get())
157 resource_collection_->SetClient(NULL);
161 bool RenderWidgetHostViewAndroid::OnMessageReceived(
162 const IPC::Message& message) {
164 IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAndroid, message)
165 IPC_MESSAGE_HANDLER(ViewHostMsg_StartContentIntent, OnStartContentIntent)
166 IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeBodyBackgroundColor,
167 OnDidChangeBodyBackgroundColor)
168 IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrame,
169 OnSetNeedsBeginFrame)
170 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
171 OnTextInputStateChanged)
172 IPC_MESSAGE_UNHANDLED(handled = false)
173 IPC_END_MESSAGE_MAP()
177 void RenderWidgetHostViewAndroid::InitAsChild(gfx::NativeView parent_view) {
181 void RenderWidgetHostViewAndroid::InitAsPopup(
182 RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) {
186 void RenderWidgetHostViewAndroid::InitAsFullscreen(
187 RenderWidgetHostView* reference_host_view) {
192 RenderWidgetHostViewAndroid::GetRenderWidgetHost() const {
196 void RenderWidgetHostViewAndroid::WasShown() {
197 if (!host_ || !host_->is_hidden())
203 void RenderWidgetHostViewAndroid::WasHidden() {
206 if (!host_ || host_->is_hidden())
209 // Inform the renderer that we are being hidden so it can reduce its resource
214 void RenderWidgetHostViewAndroid::WasResized() {
218 void RenderWidgetHostViewAndroid::SetSize(const gfx::Size& size) {
219 // Ignore the given size as only the Java code has the power to
220 // resize the view on Android.
224 void RenderWidgetHostViewAndroid::SetBounds(const gfx::Rect& rect) {
225 SetSize(rect.size());
228 WebKit::WebGLId RenderWidgetHostViewAndroid::GetScaledContentTexture(
230 gfx::Size* out_size) {
231 gfx::Size size(gfx::ToCeiledSize(
232 gfx::ScaleSize(texture_size_in_layer_, scale)));
234 if (!CompositorImpl::IsInitialized() ||
235 texture_id_in_layer_ == 0 ||
236 texture_size_in_layer_.IsEmpty() ||
239 out_size->SetSize(0, 0);
247 GLHelper* helper = ImageTransportFactoryAndroid::GetInstance()->GetGLHelper();
248 return helper->CopyAndScaleTexture(texture_id_in_layer_,
249 texture_size_in_layer_,
252 GLHelper::SCALER_QUALITY_FAST);
255 bool RenderWidgetHostViewAndroid::PopulateBitmapWithContents(jobject jbitmap) {
256 if (!CompositorImpl::IsInitialized() ||
257 texture_id_in_layer_ == 0 ||
258 texture_size_in_layer_.IsEmpty())
261 gfx::JavaBitmap bitmap(jbitmap);
263 // TODO(dtrainor): Eventually add support for multiple formats here.
264 DCHECK(bitmap.format() == ANDROID_BITMAP_FORMAT_RGBA_8888);
266 GLHelper* helper = ImageTransportFactoryAndroid::GetInstance()->GetGLHelper();
268 WebKit::WebGLId texture = helper->CopyAndScaleTexture(
269 texture_id_in_layer_,
270 texture_size_in_layer_,
273 GLHelper::SCALER_QUALITY_FAST);
277 helper->ReadbackTextureSync(texture,
278 gfx::Rect(bitmap.size()),
279 static_cast<unsigned char*> (bitmap.pixels()));
281 WebKit::WebGraphicsContext3D* context =
282 ImageTransportFactoryAndroid::GetInstance()->GetContext3D();
283 context->deleteTexture(texture);
288 bool RenderWidgetHostViewAndroid::HasValidFrame() const {
289 if (!content_view_core_)
291 if (texture_size_in_layer_.IsEmpty())
294 if (UsingDelegatedRenderer()) {
295 if (!delegated_renderer_layer_.get())
298 if (texture_id_in_layer_ == 0)
305 gfx::NativeView RenderWidgetHostViewAndroid::GetNativeView() const {
306 return content_view_core_->GetViewAndroid();
309 gfx::NativeViewId RenderWidgetHostViewAndroid::GetNativeViewId() const {
310 return reinterpret_cast<gfx::NativeViewId>(
311 const_cast<RenderWidgetHostViewAndroid*>(this));
314 gfx::NativeViewAccessible
315 RenderWidgetHostViewAndroid::GetNativeViewAccessible() {
320 void RenderWidgetHostViewAndroid::MovePluginWindows(
321 const gfx::Vector2d& scroll_offset,
322 const std::vector<WebPluginGeometry>& moves) {
323 // We don't have plugin windows on Android. Do nothing. Note: this is called
324 // from RenderWidgetHost::OnUpdateRect which is itself invoked while
325 // processing the corresponding message from Renderer.
328 void RenderWidgetHostViewAndroid::Focus() {
330 host_->SetInputMethodActive(true);
332 if (overscroll_effect_)
333 overscroll_effect_->SetEnabled(true);
336 void RenderWidgetHostViewAndroid::Blur() {
337 host_->ExecuteEditCommand("Unselect", "");
338 host_->SetInputMethodActive(false);
340 if (overscroll_effect_)
341 overscroll_effect_->SetEnabled(false);
344 bool RenderWidgetHostViewAndroid::HasFocus() const {
345 if (!content_view_core_)
346 return false; // ContentViewCore not created yet.
348 return content_view_core_->HasFocus();
351 bool RenderWidgetHostViewAndroid::IsSurfaceAvailableForCopy() const {
352 return HasValidFrame();
355 void RenderWidgetHostViewAndroid::Show() {
356 if (are_layers_attached_)
359 are_layers_attached_ = true;
365 void RenderWidgetHostViewAndroid::Hide() {
366 if (!are_layers_attached_)
369 are_layers_attached_ = false;
375 bool RenderWidgetHostViewAndroid::IsShowing() {
376 // ContentViewCoreImpl represents the native side of the Java
377 // ContentViewCore. It being NULL means that it is not attached
378 // to the View system yet, so we treat this RWHVA as hidden.
379 return are_layers_attached_ && content_view_core_;
382 gfx::Rect RenderWidgetHostViewAndroid::GetViewBounds() const {
383 if (!content_view_core_)
386 gfx::Size size = content_view_core_->GetViewportSizeDip();
387 gfx::Size offset = content_view_core_->GetViewportSizeOffsetDip();
388 size.Enlarge(-offset.width(), -offset.height());
390 return gfx::Rect(size);
393 gfx::Size RenderWidgetHostViewAndroid::GetPhysicalBackingSize() const {
394 if (!content_view_core_)
397 return content_view_core_->GetPhysicalBackingSize();
400 float RenderWidgetHostViewAndroid::GetOverdrawBottomHeight() const {
401 if (!content_view_core_)
404 return content_view_core_->GetOverdrawBottomHeightDip();
407 void RenderWidgetHostViewAndroid::UpdateCursor(const WebCursor& cursor) {
408 // There are no cursors on Android.
411 void RenderWidgetHostViewAndroid::SetIsLoading(bool is_loading) {
412 // Do nothing. The UI notification is handled through ContentViewClient which
413 // is TabContentsDelegate.
416 void RenderWidgetHostViewAndroid::TextInputTypeChanged(
417 ui::TextInputType type,
418 ui::TextInputMode input_mode,
419 bool can_compose_inline) {
420 // Unused on Android, which uses OnTextInputChanged instead.
423 int RenderWidgetHostViewAndroid::GetNativeImeAdapter() {
424 return reinterpret_cast<int>(&ime_adapter_android_);
427 void RenderWidgetHostViewAndroid::OnTextInputStateChanged(
428 const ViewHostMsg_TextInputState_Params& params) {
429 // If an acknowledgement is required for this event, regardless of how we exit
430 // from this method, we must acknowledge that we processed the input state
432 base::ScopedClosureRunner ack_caller;
433 if (params.require_ack)
434 ack_caller.Reset(base::Bind(&SendImeEventAck, host_));
439 content_view_core_->UpdateImeAdapter(
440 GetNativeImeAdapter(),
441 static_cast<int>(params.type),
442 params.value, params.selection_start, params.selection_end,
443 params.composition_start, params.composition_end,
444 params.show_ime_if_needed, params.require_ack);
447 void RenderWidgetHostViewAndroid::OnDidChangeBodyBackgroundColor(
449 if (cached_background_color_ == color)
452 cached_background_color_ = color;
453 if (content_view_core_)
454 content_view_core_->OnBackgroundColorChanged(color);
457 void RenderWidgetHostViewAndroid::SendBeginFrame(
458 const cc::BeginFrameArgs& args) {
459 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::SendBeginFrame");
463 if (flush_input_requested_) {
464 flush_input_requested_ = false;
466 content_view_core_->RemoveBeginFrameSubscriber();
469 host_->Send(new ViewMsg_BeginFrame(host_->GetRoutingID(), args));
472 void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame(
474 TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame",
476 // ContentViewCoreImpl handles multiple subscribers to the BeginFrame, so
477 // we have to make sure calls to ContentViewCoreImpl's
478 // {Add,Remove}BeginFrameSubscriber are balanced, even if
479 // RenderWidgetHostViewAndroid's may not be.
480 if (content_view_core_ && needs_begin_frame_ != enabled) {
482 content_view_core_->AddBeginFrameSubscriber();
484 content_view_core_->RemoveBeginFrameSubscriber();
485 needs_begin_frame_ = enabled;
489 void RenderWidgetHostViewAndroid::OnStartContentIntent(
490 const GURL& content_url) {
491 if (content_view_core_)
492 content_view_core_->StartContentIntent(content_url);
495 void RenderWidgetHostViewAndroid::ImeCancelComposition() {
496 ime_adapter_android_.CancelComposition();
499 void RenderWidgetHostViewAndroid::DidUpdateBackingStore(
500 const gfx::Rect& scroll_rect,
501 const gfx::Vector2d& scroll_delta,
502 const std::vector<gfx::Rect>& copy_rects,
503 const ui::LatencyInfo& latency_info) {
507 void RenderWidgetHostViewAndroid::RenderProcessGone(
508 base::TerminationStatus status, int error_code) {
512 void RenderWidgetHostViewAndroid::Destroy() {
514 content_view_core_ = NULL;
516 // The RenderWidgetHost's destruction led here, so don't call it.
522 void RenderWidgetHostViewAndroid::SetTooltipText(
523 const string16& tooltip_text) {
524 // Tooltips don't makes sense on Android.
527 void RenderWidgetHostViewAndroid::SelectionChanged(const string16& text,
529 const gfx::Range& range) {
530 RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
532 if (text.empty() || range.is_empty() || !content_view_core_)
534 size_t pos = range.GetMin() - offset;
535 size_t n = range.length();
537 DCHECK(pos + n <= text.length()) << "The text can not fully cover range.";
538 if (pos >= text.length()) {
539 NOTREACHED() << "The text can not cover range.";
543 std::string utf8_selection = UTF16ToUTF8(text.substr(pos, n));
545 content_view_core_->OnSelectionChanged(utf8_selection);
548 void RenderWidgetHostViewAndroid::SelectionBoundsChanged(
549 const ViewHostMsg_SelectionBounds_Params& params) {
550 if (content_view_core_) {
551 content_view_core_->OnSelectionBoundsChanged(params);
555 void RenderWidgetHostViewAndroid::ScrollOffsetChanged() {
558 BackingStore* RenderWidgetHostViewAndroid::AllocBackingStore(
559 const gfx::Size& size) {
564 void RenderWidgetHostViewAndroid::SetBackground(const SkBitmap& background) {
565 RenderWidgetHostViewBase::SetBackground(background);
566 host_->Send(new ViewMsg_SetBackground(host_->GetRoutingID(), background));
569 void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
570 const gfx::Rect& src_subrect,
571 const gfx::Size& dst_size,
572 const base::Callback<void(bool, const SkBitmap&)>& callback) {
573 if (!IsSurfaceAvailableForCopy()) {
574 callback.Run(false, SkBitmap());
578 const gfx::Display& display =
579 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
580 float device_scale_factor = display.device_scale_factor();
582 DCHECK_EQ(device_scale_factor,
583 ui::GetImageScale(GetScaleFactorForView(this)));
585 const gfx::Size& dst_size_in_pixel = ConvertViewSizeToPixel(this, dst_size);
586 gfx::Rect src_subrect_in_pixel =
587 ConvertRectToPixel(device_scale_factor, src_subrect);
589 scoped_ptr<cc::CopyOutputRequest> request;
590 if (src_subrect_in_pixel.size() == dst_size_in_pixel) {
591 request = cc::CopyOutputRequest::CreateBitmapRequest(base::Bind(
592 &RenderWidgetHostViewAndroid::PrepareBitmapCopyOutputResult,
596 request = cc::CopyOutputRequest::CreateRequest(base::Bind(
597 &RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult,
601 request->set_area(src_subrect_in_pixel);
602 layer_->RequestCopyOfOutput(request.Pass());
605 void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame(
606 const gfx::Rect& src_subrect,
607 const scoped_refptr<media::VideoFrame>& target,
608 const base::Callback<void(bool)>& callback) {
613 bool RenderWidgetHostViewAndroid::CanCopyToVideoFrame() const {
617 void RenderWidgetHostViewAndroid::ShowDisambiguationPopup(
618 const gfx::Rect& target_rect, const SkBitmap& zoomed_bitmap) {
619 if (!content_view_core_)
622 content_view_core_->ShowDisambiguationPopup(target_rect, zoomed_bitmap);
625 SyntheticGesture* RenderWidgetHostViewAndroid::CreateSmoothScrollGesture(
626 bool scroll_down, int pixels_to_scroll, int mouse_event_x,
628 return new GenericTouchGestureAndroid(
629 GetRenderWidgetHost(),
630 content_view_core_->CreateOnePointTouchGesture(
631 mouse_event_x, mouse_event_y,
632 0, scroll_down ? -pixels_to_scroll : pixels_to_scroll));
635 SyntheticGesture* RenderWidgetHostViewAndroid::CreatePinchGesture(
636 bool zoom_in, int pixels_to_move, int anchor_x,
638 int distance_between_pointers = zoom_in ?
639 kMinimumPointerDistance : (kMinimumPointerDistance + pixels_to_move);
640 return new GenericTouchGestureAndroid(
641 GetRenderWidgetHost(),
642 content_view_core_->CreateTwoPointTouchGesture(
643 anchor_x, anchor_y - distance_between_pointers / 2,
644 0, (zoom_in ? -pixels_to_move : pixels_to_move) / 2,
645 anchor_x, anchor_y + distance_between_pointers / 2,
646 0, (zoom_in ? pixels_to_move : -pixels_to_move) / 2));
649 void RenderWidgetHostViewAndroid::OnAcceleratedCompositingStateChange() {
652 void RenderWidgetHostViewAndroid::SendDelegatedFrameAck(
653 uint32 output_surface_id) {
654 cc::CompositorFrameAck ack;
655 if (resource_collection_.get())
656 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
657 RenderWidgetHostImpl::SendSwapCompositorFrameAck(host_->GetRoutingID(),
659 host_->GetProcess()->GetID(),
663 void RenderWidgetHostViewAndroid::UnusedResourcesAreAvailable() {
664 // TODO(danakj): If no ack is pending, collect and send resources now.
667 void RenderWidgetHostViewAndroid::DestroyDelegatedContent() {
668 if (are_layers_attached_)
670 frame_provider_ = NULL;
671 delegated_renderer_layer_ = NULL;
675 void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
676 uint32 output_surface_id,
677 scoped_ptr<cc::DelegatedFrameData> frame_data) {
678 bool has_content = !texture_size_in_layer_.IsEmpty();
680 if (output_surface_id != last_output_surface_id_) {
681 // TODO(danakj): Lose all resources and send them back here, such as:
682 // resource_collection_->LoseAllResources();
683 // SendReturnedDelegatedResources(last_output_surface_id_);
685 // Drop the cc::DelegatedFrameResourceCollection so that we will not return
686 // any resources from the old output surface with the new output surface id.
687 if (resource_collection_.get()) {
688 resource_collection_->SetClient(NULL);
689 resource_collection_ = NULL;
691 DestroyDelegatedContent();
693 last_output_surface_id_ = output_surface_id;
697 DestroyDelegatedContent();
699 if (!resource_collection_.get()) {
700 resource_collection_ = new cc::DelegatedFrameResourceCollection;
701 resource_collection_->SetClient(this);
703 if (!frame_provider_ ||
704 texture_size_in_layer_ != frame_provider_->frame_size()) {
705 if (are_layers_attached_)
707 frame_provider_ = new cc::DelegatedFrameProvider(
708 resource_collection_.get(), frame_data.Pass());
709 delegated_renderer_layer_ =
710 cc::DelegatedRendererLayer::Create(this, frame_provider_);
711 layer_ = delegated_renderer_layer_;
712 if (are_layers_attached_)
715 frame_provider_->SetFrameData(frame_data.Pass());
719 if (delegated_renderer_layer_.get()) {
720 delegated_renderer_layer_->SetDisplaySize(texture_size_in_layer_);
721 delegated_renderer_layer_->SetIsDrawable(true);
722 delegated_renderer_layer_->SetContentsOpaque(true);
723 delegated_renderer_layer_->SetBounds(content_size_in_layer_);
724 delegated_renderer_layer_->SetNeedsDisplay();
727 base::Closure ack_callback =
728 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck,
729 weak_ptr_factory_.GetWeakPtr(),
732 if (host_->is_hidden())
735 ack_callbacks_.push(ack_callback);
738 void RenderWidgetHostViewAndroid::ComputeContentsSize(
739 const cc::CompositorFrameMetadata& frame_metadata) {
740 // Calculate the content size. This should be 0 if the texture_size is 0.
741 gfx::Vector2dF offset;
742 if (texture_size_in_layer_.GetArea() > 0)
743 offset = frame_metadata.location_bar_content_translation;
744 offset.set_y(offset.y() + frame_metadata.overdraw_bottom_height);
745 offset.Scale(frame_metadata.device_scale_factor);
746 content_size_in_layer_ =
747 gfx::Size(texture_size_in_layer_.width() - offset.x(),
748 texture_size_in_layer_.height() - offset.y());
749 // Content size changes should be reflected in associated animation effects.
750 UpdateAnimationSize(frame_metadata);
753 void RenderWidgetHostViewAndroid::OnSwapCompositorFrame(
754 uint32 output_surface_id,
755 scoped_ptr<cc::CompositorFrame> frame) {
756 // Always let ContentViewCore know about the new frame first, so it can decide
757 // to schedule a Draw immediately when it sees the texture layer invalidation.
758 UpdateContentViewCoreFrameMetadata(frame->metadata);
760 if (frame->delegated_frame_data) {
761 DCHECK(UsingDelegatedRenderer());
763 DCHECK(frame->delegated_frame_data);
764 DCHECK(!frame->delegated_frame_data->render_pass_list.empty());
766 cc::RenderPass* root_pass =
767 frame->delegated_frame_data->render_pass_list.back();
768 texture_size_in_layer_ = root_pass->output_rect.size();
769 ComputeContentsSize(frame->metadata);
771 SwapDelegatedFrame(output_surface_id, frame->delegated_frame_data.Pass());
775 DCHECK(!UsingDelegatedRenderer());
777 if (!frame->gl_frame_data || frame->gl_frame_data->mailbox.IsZero())
780 if (output_surface_id != last_output_surface_id_) {
781 current_mailbox_ = gpu::Mailbox();
782 last_output_surface_id_ = kUndefinedOutputSurfaceId;
785 base::Closure callback = base::Bind(&InsertSyncPointAndAckForCompositor,
786 host_->GetProcess()->GetID(),
788 host_->GetRoutingID(),
790 texture_size_in_layer_);
791 ImageTransportFactoryAndroid::GetInstance()->WaitSyncPoint(
792 frame->gl_frame_data->sync_point);
794 texture_size_in_layer_ = frame->gl_frame_data->size;
795 ComputeContentsSize(frame->metadata);
797 if (layer_->layer_tree_host())
798 layer_->layer_tree_host()->SetLatencyInfo(frame->metadata.latency_info);
800 BuffersSwapped(frame->gl_frame_data->mailbox, output_surface_id, callback);
803 void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
804 const cc::CompositorFrameMetadata& frame_metadata) {
805 // This is a subset of OnSwapCompositorFrame() used in the synchronous
807 UpdateContentViewCoreFrameMetadata(frame_metadata);
808 ComputeContentsSize(frame_metadata);
811 void RenderWidgetHostViewAndroid::UpdateContentViewCoreFrameMetadata(
812 const cc::CompositorFrameMetadata& frame_metadata) {
813 if (content_view_core_) {
814 // All offsets and sizes are in CSS pixels.
815 content_view_core_->UpdateFrameInfo(
816 frame_metadata.root_scroll_offset,
817 frame_metadata.page_scale_factor,
818 gfx::Vector2dF(frame_metadata.min_page_scale_factor,
819 frame_metadata.max_page_scale_factor),
820 frame_metadata.root_layer_size,
821 frame_metadata.viewport_size,
822 frame_metadata.location_bar_offset,
823 frame_metadata.location_bar_content_translation,
824 frame_metadata.overdraw_bottom_height);
828 void RenderWidgetHostViewAndroid::AcceleratedSurfaceBuffersSwapped(
829 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
831 NOTREACHED() << "Deprecated. Use --composite-to-mailbox.";
833 if (params.mailbox_name.empty())
836 std::string return_mailbox;
837 if (!current_mailbox_.IsZero()) {
838 return_mailbox.assign(
839 reinterpret_cast<const char*>(current_mailbox_.name),
840 sizeof(current_mailbox_.name));
843 base::Closure callback = base::Bind(&InsertSyncPointAndAckForGpu,
844 gpu_host_id, params.route_id,
847 gpu::Mailbox mailbox;
848 std::copy(params.mailbox_name.data(),
849 params.mailbox_name.data() + params.mailbox_name.length(),
850 reinterpret_cast<char*>(mailbox.name));
852 texture_size_in_layer_ = params.size;
853 content_size_in_layer_ = params.size;
855 BuffersSwapped(mailbox, kUndefinedOutputSurfaceId, callback);
858 void RenderWidgetHostViewAndroid::BuffersSwapped(
859 const gpu::Mailbox& mailbox,
860 uint32_t output_surface_id,
861 const base::Closure& ack_callback) {
862 ImageTransportFactoryAndroid* factory =
863 ImageTransportFactoryAndroid::GetInstance();
865 // TODO(sievers): When running the impl thread in the browser we
866 // need to delay the ACK until after commit and use more than a single
868 DCHECK(!CompositorImpl::IsThreadingEnabled());
870 if (!texture_id_in_layer_) {
871 texture_id_in_layer_ = factory->CreateTexture();
872 texture_layer_->SetIsDrawable(true);
873 texture_layer_->SetContentsOpaque(true);
876 ImageTransportFactoryAndroid::GetInstance()->AcquireTexture(
877 texture_id_in_layer_, mailbox.name);
881 current_mailbox_ = mailbox;
882 last_output_surface_id_ = output_surface_id;
884 if (host_->is_hidden())
887 ack_callbacks_.push(ack_callback);
890 void RenderWidgetHostViewAndroid::AttachLayers() {
891 if (!content_view_core_)
896 content_view_core_->AttachLayer(layer_);
899 void RenderWidgetHostViewAndroid::RemoveLayers() {
900 if (!content_view_core_)
905 if (overscroll_effect_)
906 content_view_core_->RemoveLayer(overscroll_effect_->root_layer());
908 content_view_core_->RemoveLayer(layer_);
911 bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) {
912 if (!overscroll_effect_)
915 bool overscroll_running = overscroll_effect_->Animate(frame_time);
916 if (!overscroll_running)
917 content_view_core_->RemoveLayer(overscroll_effect_->root_layer());
919 return overscroll_running;
922 void RenderWidgetHostViewAndroid::CreateOverscrollEffectIfNecessary() {
923 if (!overscroll_effect_enabled_ || overscroll_effect_)
926 overscroll_effect_ = OverscrollGlow::Create(true, content_size_in_layer_);
928 // Prevent future creation attempts on failure.
929 if (!overscroll_effect_)
930 overscroll_effect_enabled_ = false;
933 void RenderWidgetHostViewAndroid::UpdateAnimationSize(
934 const cc::CompositorFrameMetadata& frame_metadata) {
935 if (!overscroll_effect_)
937 // Disable edge effects for axes on which scrolling is impossible.
938 gfx::SizeF ceiled_viewport_size =
939 gfx::ToCeiledSize(frame_metadata.viewport_size);
940 overscroll_effect_->set_horizontal_overscroll_enabled(
941 ceiled_viewport_size.width() < frame_metadata.root_layer_size.width());
942 overscroll_effect_->set_vertical_overscroll_enabled(
943 ceiled_viewport_size.height() < frame_metadata.root_layer_size.height());
944 overscroll_effect_->set_size(content_size_in_layer_);
947 void RenderWidgetHostViewAndroid::ScheduleAnimationIfNecessary() {
948 if (!content_view_core_ || !overscroll_effect_)
951 if (overscroll_effect_->NeedsAnimate() && are_layers_attached_) {
952 if (!overscroll_effect_->root_layer()->parent())
953 content_view_core_->AttachLayer(overscroll_effect_->root_layer());
954 content_view_core_->SetNeedsAnimate();
956 content_view_core_->RemoveLayer(overscroll_effect_->root_layer());
960 void RenderWidgetHostViewAndroid::AcceleratedSurfacePostSubBuffer(
961 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
966 void RenderWidgetHostViewAndroid::AcceleratedSurfaceSuspend() {
970 void RenderWidgetHostViewAndroid::AcceleratedSurfaceRelease() {
971 // This tells us we should free the frontbuffer.
972 if (texture_id_in_layer_) {
973 texture_layer_->SetTextureId(0);
974 texture_layer_->SetIsDrawable(false);
975 ImageTransportFactoryAndroid::GetInstance()->DeleteTexture(
976 texture_id_in_layer_);
977 texture_id_in_layer_ = 0;
978 current_mailbox_ = gpu::Mailbox();
979 last_output_surface_id_ = kUndefinedOutputSurfaceId;
981 if (delegated_renderer_layer_.get())
982 DestroyDelegatedContent();
985 bool RenderWidgetHostViewAndroid::HasAcceleratedSurface(
986 const gfx::Size& desired_size) {
991 void RenderWidgetHostViewAndroid::GetScreenInfo(WebKit::WebScreenInfo* result) {
992 // ScreenInfo isn't tied to the widget on Android. Always return the default.
993 RenderWidgetHostViewBase::GetDefaultScreenInfo(result);
996 // TODO(jrg): Find out the implications and answer correctly here,
997 // as we are returning the WebView and not root window bounds.
998 gfx::Rect RenderWidgetHostViewAndroid::GetBoundsInRootWindow() {
999 return GetViewBounds();
1002 gfx::GLSurfaceHandle RenderWidgetHostViewAndroid::GetCompositingSurface() {
1003 return gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::TEXTURE_TRANSPORT);
1006 void RenderWidgetHostViewAndroid::ProcessAckedTouchEvent(
1007 const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
1008 if (content_view_core_)
1009 content_view_core_->ConfirmTouchEvent(ack_result);
1012 void RenderWidgetHostViewAndroid::SetHasHorizontalScrollbar(
1013 bool has_horizontal_scrollbar) {
1014 // intentionally empty, like RenderWidgetHostViewViews
1017 void RenderWidgetHostViewAndroid::SetScrollOffsetPinning(
1018 bool is_pinned_to_left, bool is_pinned_to_right) {
1019 // intentionally empty, like RenderWidgetHostViewViews
1022 void RenderWidgetHostViewAndroid::UnhandledWheelEvent(
1023 const WebKit::WebMouseWheelEvent& event) {
1024 // intentionally empty, like RenderWidgetHostViewViews
1027 void RenderWidgetHostViewAndroid::GestureEventAck(
1028 int gesture_event_type,
1029 InputEventAckState ack_result) {
1030 if (gesture_event_type == WebKit::WebInputEvent::GestureScrollUpdate &&
1031 ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) {
1032 content_view_core_->OnScrollUpdateGestureConsumed();
1034 if (gesture_event_type == WebKit::WebInputEvent::GestureFlingStart &&
1035 ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) {
1036 content_view_core_->UnhandledFlingStartEvent();
1040 InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
1041 const WebKit::WebInputEvent& input_event) {
1043 SynchronousCompositorImpl* compositor =
1044 SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
1045 host_->GetRoutingID());
1047 return compositor->HandleInputEvent(input_event);
1049 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1052 void RenderWidgetHostViewAndroid::OnSetNeedsFlushInput() {
1053 if (flush_input_requested_ || !content_view_core_)
1055 flush_input_requested_ = true;
1056 content_view_core_->AddBeginFrameSubscriber();
1059 void RenderWidgetHostViewAndroid::OnAccessibilityEvents(
1060 const std::vector<AccessibilityHostMsg_EventParams>& params) {
1061 if (!host_ || host_->accessibility_mode() != AccessibilityModeComplete)
1064 if (!GetBrowserAccessibilityManager()) {
1065 base::android::ScopedJavaLocalRef<jobject> obj;
1066 if (content_view_core_)
1067 obj = content_view_core_->GetJavaObject();
1068 SetBrowserAccessibilityManager(
1069 new BrowserAccessibilityManagerAndroid(
1070 obj, BrowserAccessibilityManagerAndroid::GetEmptyDocument(), this));
1072 GetBrowserAccessibilityManager()->OnAccessibilityEvents(params);
1075 void RenderWidgetHostViewAndroid::SetAccessibilityFocus(int acc_obj_id) {
1079 host_->AccessibilitySetFocus(acc_obj_id);
1082 void RenderWidgetHostViewAndroid::AccessibilityDoDefaultAction(int acc_obj_id) {
1086 host_->AccessibilityDoDefaultAction(acc_obj_id);
1089 void RenderWidgetHostViewAndroid::AccessibilityScrollToMakeVisible(
1090 int acc_obj_id, gfx::Rect subfocus) {
1094 host_->AccessibilityScrollToMakeVisible(acc_obj_id, subfocus);
1097 void RenderWidgetHostViewAndroid::AccessibilityScrollToPoint(
1098 int acc_obj_id, gfx::Point point) {
1102 host_->AccessibilityScrollToPoint(acc_obj_id, point);
1105 void RenderWidgetHostViewAndroid::AccessibilitySetTextSelection(
1106 int acc_obj_id, int start_offset, int end_offset) {
1110 host_->AccessibilitySetTextSelection(
1111 acc_obj_id, start_offset, end_offset);
1114 gfx::Point RenderWidgetHostViewAndroid::GetLastTouchEventLocation() const {
1116 // Only used on Win8
1117 return gfx::Point();
1120 void RenderWidgetHostViewAndroid::FatalAccessibilityTreeError() {
1124 host_->FatalAccessibilityTreeError();
1125 SetBrowserAccessibilityManager(NULL);
1128 bool RenderWidgetHostViewAndroid::LockMouse() {
1133 void RenderWidgetHostViewAndroid::UnlockMouse() {
1137 // Methods called from the host to the render
1139 void RenderWidgetHostViewAndroid::SendKeyEvent(
1140 const NativeWebKeyboardEvent& event) {
1142 host_->ForwardKeyboardEvent(event);
1145 void RenderWidgetHostViewAndroid::SendTouchEvent(
1146 const WebKit::WebTouchEvent& event) {
1148 host_->ForwardTouchEventWithLatencyInfo(event, ui::LatencyInfo());
1152 void RenderWidgetHostViewAndroid::SendMouseEvent(
1153 const WebKit::WebMouseEvent& event) {
1155 host_->ForwardMouseEvent(event);
1158 void RenderWidgetHostViewAndroid::SendMouseWheelEvent(
1159 const WebKit::WebMouseWheelEvent& event) {
1161 host_->ForwardWheelEvent(event);
1164 void RenderWidgetHostViewAndroid::SendGestureEvent(
1165 const WebKit::WebGestureEvent& event) {
1166 // Sending a gesture that may trigger overscroll should resume the effect.
1167 if (overscroll_effect_)
1168 overscroll_effect_->SetEnabled(true);
1171 host_->ForwardGestureEvent(event);
1174 void RenderWidgetHostViewAndroid::SelectRange(const gfx::Point& start,
1175 const gfx::Point& end) {
1177 host_->SelectRange(start, end);
1180 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point& point) {
1182 host_->MoveCaret(point);
1185 void RenderWidgetHostViewAndroid::RequestContentClipping(
1186 const gfx::Rect& clipping,
1187 const gfx::Size& content_size) {
1188 // A focused view provides its own clipping.
1192 ClipContents(clipping, content_size);
1195 void RenderWidgetHostViewAndroid::ResetClipping() {
1196 ClipContents(gfx::Rect(gfx::Point(), content_size_in_layer_),
1197 content_size_in_layer_);
1200 void RenderWidgetHostViewAndroid::ClipContents(const gfx::Rect& clipping,
1201 const gfx::Size& content_size) {
1202 if (!texture_id_in_layer_ || content_size_in_layer_.IsEmpty())
1205 gfx::Size clipped_content(content_size_in_layer_);
1206 clipped_content.SetToMin(clipping.size());
1207 texture_layer_->SetBounds(clipped_content);
1208 texture_layer_->SetNeedsDisplay();
1210 if (texture_size_in_layer_.IsEmpty()) {
1211 texture_layer_->SetUV(gfx::PointF(), gfx::PointF());
1216 clipping.x() + content_size_in_layer_.width() - content_size.width(),
1217 clipping.y() + content_size_in_layer_.height() - content_size.height());
1218 offset.SetToMax(gfx::PointF());
1220 gfx::Vector2dF uv_scale(1.f / texture_size_in_layer_.width(),
1221 1.f / texture_size_in_layer_.height());
1222 texture_layer_->SetUV(
1223 gfx::PointF(offset.x() * uv_scale.x(),
1224 offset.y() * uv_scale.y()),
1225 gfx::PointF((offset.x() + clipped_content.width()) * uv_scale.x(),
1226 (offset.y() + clipped_content.height()) * uv_scale.y()));
1229 SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const {
1230 return cached_background_color_;
1233 void RenderWidgetHostViewAndroid::OnOverscrolled(
1234 gfx::Vector2dF accumulated_overscroll,
1235 gfx::Vector2dF current_fling_velocity) {
1236 CreateOverscrollEffectIfNecessary();
1237 if (!overscroll_effect_)
1240 overscroll_effect_->OnOverscrolled(base::TimeTicks::Now(),
1241 accumulated_overscroll,
1242 current_fling_velocity);
1243 ScheduleAnimationIfNecessary();
1246 void RenderWidgetHostViewAndroid::SetContentViewCore(
1247 ContentViewCoreImpl* content_view_core) {
1250 if (are_layers_attached_)
1253 content_view_core_ = content_view_core;
1255 if (GetBrowserAccessibilityManager()) {
1256 base::android::ScopedJavaLocalRef<jobject> obj;
1257 if (content_view_core_)
1258 obj = content_view_core_->GetJavaObject();
1259 GetBrowserAccessibilityManager()->ToBrowserAccessibilityManagerAndroid()->
1260 SetContentViewCore(obj);
1263 if (are_layers_attached_)
1267 void RenderWidgetHostViewAndroid::RunAckCallbacks() {
1268 while (!ack_callbacks_.empty()) {
1269 ack_callbacks_.front().Run();
1270 ack_callbacks_.pop();
1274 void RenderWidgetHostViewAndroid::HasTouchEventHandlers(
1275 bool need_touch_events) {
1276 if (content_view_core_)
1277 content_view_core_->HasTouchEventHandlers(need_touch_events);
1280 unsigned RenderWidgetHostViewAndroid::PrepareTexture() {
1282 return texture_id_in_layer_;
1285 void RenderWidgetHostViewAndroid::DidCommitFrameData() {
1289 WebKit::WebGraphicsContext3D* RenderWidgetHostViewAndroid::Context3d() {
1290 return ImageTransportFactoryAndroid::GetInstance()->GetContext3D();
1293 bool RenderWidgetHostViewAndroid::PrepareTextureMailbox(
1294 cc::TextureMailbox* mailbox,
1295 scoped_ptr<cc::SingleReleaseCallback>* release_callback,
1296 bool use_shared_memory) {
1300 void RenderWidgetHostViewAndroid::OnLostResources() {
1301 if (texture_layer_.get())
1302 texture_layer_->SetIsDrawable(false);
1303 if (delegated_renderer_layer_.get())
1304 DestroyDelegatedContent();
1305 texture_id_in_layer_ = 0;
1310 void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
1311 const gfx::Size& dst_size_in_pixel,
1312 const base::Callback<void(bool, const SkBitmap&)>& callback,
1313 scoped_ptr<cc::CopyOutputResult> result) {
1314 DCHECK(result->HasTexture());
1315 base::ScopedClosureRunner scoped_callback_runner(
1316 base::Bind(callback, false, SkBitmap()));
1318 if (!result->HasTexture() || result->IsEmpty() || result->size().IsEmpty())
1321 scoped_ptr<SkBitmap> bitmap(new SkBitmap);
1322 bitmap->setConfig(SkBitmap::kARGB_8888_Config,
1323 dst_size_in_pixel.width(), dst_size_in_pixel.height(),
1324 0, kOpaque_SkAlphaType);
1325 if (!bitmap->allocPixels())
1328 ImageTransportFactoryAndroid* factory =
1329 ImageTransportFactoryAndroid::GetInstance();
1330 GLHelper* gl_helper = factory->GetGLHelper();
1334 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock(
1335 new SkAutoLockPixels(*bitmap));
1336 uint8* pixels = static_cast<uint8*>(bitmap->getPixels());
1338 cc::TextureMailbox texture_mailbox;
1339 scoped_ptr<cc::SingleReleaseCallback> release_callback;
1340 result->TakeTexture(&texture_mailbox, &release_callback);
1341 DCHECK(texture_mailbox.IsTexture());
1342 if (!texture_mailbox.IsTexture())
1345 ignore_result(scoped_callback_runner.Release());
1347 gl_helper->CropScaleReadbackAndCleanMailbox(
1348 texture_mailbox.name(),
1349 texture_mailbox.sync_point(),
1351 gfx::Rect(result->size()),
1354 base::Bind(&CopyFromCompositingSurfaceFinished,
1356 base::Passed(&release_callback),
1357 base::Passed(&bitmap),
1358 base::Passed(&bitmap_pixels_lock)));
1362 void RenderWidgetHostViewAndroid::PrepareBitmapCopyOutputResult(
1363 const gfx::Size& dst_size_in_pixel,
1364 const base::Callback<void(bool, const SkBitmap&)>& callback,
1365 scoped_ptr<cc::CopyOutputResult> result) {
1366 DCHECK(result->HasBitmap());
1367 base::ScopedClosureRunner scoped_callback_runner(
1368 base::Bind(callback, false, SkBitmap()));
1370 if (!result->HasBitmap() || result->IsEmpty() || result->size().IsEmpty())
1373 scoped_ptr<SkBitmap> source = result->TakeBitmap();
1378 DCHECK_EQ(source->width(), dst_size_in_pixel.width());
1379 DCHECK_EQ(source->height(), dst_size_in_pixel.height());
1381 ignore_result(scoped_callback_runner.Release());
1382 callback.Run(true, *source);
1386 void RenderWidgetHostViewPort::GetDefaultScreenInfo(
1387 WebKit::WebScreenInfo* results) {
1388 const gfx::Display& display =
1389 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
1390 results->rect = display.bounds();
1391 // TODO(husky): Remove any system controls from availableRect.
1392 results->availableRect = display.work_area();
1393 results->deviceScaleFactor = display.device_scale_factor();
1394 gfx::DeviceDisplayInfo info;
1395 results->depth = info.GetBitsPerPixel();
1396 results->depthPerComponent = info.GetBitsPerComponent();
1397 results->isMonochrome = (results->depthPerComponent == 0);
1400 ////////////////////////////////////////////////////////////////////////////////
1401 // RenderWidgetHostView, public:
1404 RenderWidgetHostView*
1405 RenderWidgetHostView::CreateViewForWidget(RenderWidgetHost* widget) {
1406 RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(widget);
1407 return new RenderWidgetHostViewAndroid(rwhi, NULL);
1410 } // namespace content