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/base/latency_info_swap_promise.h"
21 #include "cc/layers/delegated_frame_provider.h"
22 #include "cc/layers/delegated_renderer_layer.h"
23 #include "cc/layers/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/viewport_selection_bound.h"
29 #include "cc/resources/single_release_callback.h"
30 #include "cc/trees/layer_tree_host.h"
31 #include "content/browser/accessibility/browser_accessibility_manager_android.h"
32 #include "content/browser/android/composited_touch_handle_drawable.h"
33 #include "content/browser/android/content_view_core_impl.h"
34 #include "content/browser/android/edge_effect.h"
35 #include "content/browser/android/edge_effect_l.h"
36 #include "content/browser/android/in_process/synchronous_compositor_impl.h"
37 #include "content/browser/android/overscroll_glow.h"
38 #include "content/browser/devtools/render_view_devtools_agent_host.h"
39 #include "content/browser/gpu/compositor_util.h"
40 #include "content/browser/gpu/gpu_data_manager_impl.h"
41 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
42 #include "content/browser/gpu/gpu_surface_tracker.h"
43 #include "content/browser/media/media_web_contents_observer.h"
44 #include "content/browser/renderer_host/compositor_impl_android.h"
45 #include "content/browser/renderer_host/dip_util.h"
46 #include "content/browser/renderer_host/image_transport_factory_android.h"
47 #include "content/browser/renderer_host/input/synthetic_gesture_target_android.h"
48 #include "content/browser/renderer_host/input/touch_selection_controller.h"
49 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
50 #include "content/browser/renderer_host/input/web_input_event_util.h"
51 #include "content/browser/renderer_host/render_process_host_impl.h"
52 #include "content/browser/renderer_host/render_view_host_impl.h"
53 #include "content/browser/renderer_host/render_widget_host_impl.h"
54 #include "content/common/gpu/client/gl_helper.h"
55 #include "content/common/gpu/gpu_messages.h"
56 #include "content/common/input/did_overscroll_params.h"
57 #include "content/common/input_messages.h"
58 #include "content/common/view_messages.h"
59 #include "content/public/browser/browser_thread.h"
60 #include "content/public/browser/devtools_agent_host.h"
61 #include "content/public/browser/render_view_host.h"
62 #include "content/public/common/content_switches.h"
63 #include "gpu/command_buffer/client/gles2_interface.h"
64 #include "gpu/config/gpu_driver_bug_workaround_type.h"
65 #include "skia/ext/image_operations.h"
66 #include "third_party/khronos/GLES2/gl2.h"
67 #include "third_party/khronos/GLES2/gl2ext.h"
68 #include "third_party/skia/include/core/SkCanvas.h"
69 #include "ui/base/android/window_android.h"
70 #include "ui/base/android/window_android_compositor.h"
71 #include "ui/events/gesture_detection/gesture_config_helper.h"
72 #include "ui/events/gesture_detection/motion_event.h"
73 #include "ui/gfx/android/device_display_info.h"
74 #include "ui/gfx/android/java_bitmap.h"
75 #include "ui/gfx/android/view_configuration.h"
76 #include "ui/gfx/display.h"
77 #include "ui/gfx/screen.h"
78 #include "ui/gfx/size_conversions.h"
84 const int kUndefinedOutputSurfaceId = -1;
86 // Used to accomodate finite precision when comparing scaled viewport and
87 // content widths. While this value may seem large, width=device-width on an N7
88 // V1 saw errors of ~0.065 between computed window and content widths.
89 const float kMobileViewportWidthEpsilon = 0.15f;
91 // Used for conditional creation of EdgeEffect types for overscroll.
92 const int kKitKatMR2SDKVersion = 19;
94 static const char kAsyncReadBackString[] = "Compositing.CopyFromSurfaceTime";
96 // Sends an acknowledgement to the renderer of a processed IME event.
97 void SendImeEventAck(RenderWidgetHostImpl* host) {
98 host->Send(new ViewMsg_ImeEventAck(host->GetRoutingID()));
101 void CopyFromCompositingSurfaceFinished(
102 const base::Callback<void(bool, const SkBitmap&)>& callback,
103 scoped_ptr<cc::SingleReleaseCallback> release_callback,
104 scoped_ptr<SkBitmap> bitmap,
105 const base::TimeTicks& start_time,
106 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
109 "cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceFinished");
110 bitmap_pixels_lock.reset();
111 uint32 sync_point = 0;
113 GLHelper* gl_helper =
114 ImageTransportFactoryAndroid::GetInstance()->GetGLHelper();
115 sync_point = gl_helper->InsertSyncPoint();
117 bool lost_resource = sync_point == 0;
118 release_callback->Run(sync_point, lost_resource);
119 UMA_HISTOGRAM_TIMES(kAsyncReadBackString,
120 base::TimeTicks::Now() - start_time);
121 callback.Run(result, *bitmap);
124 ui::LatencyInfo CreateLatencyInfo(const blink::WebInputEvent& event) {
125 ui::LatencyInfo latency_info;
126 // The latency number should only be added if the timestamp is valid.
127 if (event.timeStampSeconds) {
128 const int64 time_micros = static_cast<int64>(
129 event.timeStampSeconds * base::Time::kMicrosecondsPerSecond);
130 latency_info.AddLatencyNumberWithTimestamp(
131 ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
134 base::TimeTicks() + base::TimeDelta::FromMicroseconds(time_micros),
140 OverscrollGlow::DisplayParameters CreateOverscrollDisplayParameters(
141 const cc::CompositorFrameMetadata& frame_metadata) {
142 const float scale_factor =
143 frame_metadata.page_scale_factor * frame_metadata.device_scale_factor;
145 // Compute the size and offsets for each edge, where each effect is sized to
146 // the viewport and offset by the distance of each viewport edge to the
147 // respective content edge.
148 OverscrollGlow::DisplayParameters params;
149 params.size = gfx::ScaleSize(
150 frame_metadata.scrollable_viewport_size, scale_factor);
151 params.edge_offsets[OverscrollGlow::EDGE_TOP] =
152 -frame_metadata.root_scroll_offset.y() * scale_factor;
153 params.edge_offsets[OverscrollGlow::EDGE_LEFT] =
154 -frame_metadata.root_scroll_offset.x() * scale_factor;
155 params.edge_offsets[OverscrollGlow::EDGE_BOTTOM] =
156 (frame_metadata.root_layer_size.height() -
157 frame_metadata.root_scroll_offset.y() -
158 frame_metadata.scrollable_viewport_size.height()) *
160 params.edge_offsets[OverscrollGlow::EDGE_RIGHT] =
161 (frame_metadata.root_layer_size.width() -
162 frame_metadata.root_scroll_offset.x() -
163 frame_metadata.scrollable_viewport_size.width()) *
169 bool UseEdgeEffectL() {
170 static bool use_edge_effect_l =
171 base::android::BuildInfo::GetInstance()->sdk_int() > kKitKatMR2SDKVersion;
172 return use_edge_effect_l;
175 scoped_ptr<EdgeEffectBase> CreateEdgeEffect(
176 ui::SystemUIResourceManager* resource_manager,
177 float device_scale_factor) {
178 DCHECK(resource_manager);
179 if (UseEdgeEffectL())
180 return scoped_ptr<EdgeEffectBase>(new EdgeEffectL(resource_manager));
182 return scoped_ptr<EdgeEffectBase>(
183 new EdgeEffect(resource_manager, device_scale_factor));
186 scoped_ptr<OverscrollGlow> CreateOverscrollEffect(
187 ContentViewCore* content_view_core) {
188 DCHECK(content_view_core);
189 ui::WindowAndroidCompositor* compositor =
190 content_view_core->GetWindowAndroid()->GetCompositor();
192 ui::SystemUIResourceManager* system_resource_manager =
193 &compositor->GetSystemUIResourceManager();
195 if (UseEdgeEffectL())
196 EdgeEffectL::PreloadResources(system_resource_manager);
198 EdgeEffect::PreloadResources(system_resource_manager);
200 return make_scoped_ptr(
201 new OverscrollGlow(base::Bind(&CreateEdgeEffect,
202 system_resource_manager,
203 content_view_core->GetDpiScale())));
206 scoped_ptr<TouchSelectionController> CreateSelectionController(
207 TouchSelectionControllerClient* client,
208 ContentViewCore* content_view_core) {
210 DCHECK(content_view_core);
211 int tap_timeout_ms = gfx::ViewConfiguration::GetTapTimeoutInMs();
212 int touch_slop_pixels = gfx::ViewConfiguration::GetTouchSlopInPixels();
213 return make_scoped_ptr(new TouchSelectionController(
215 base::TimeDelta::FromMilliseconds(tap_timeout_ms),
216 touch_slop_pixels / content_view_core->GetDpiScale()));
219 ui::GestureProvider::Config CreateGestureProviderConfig() {
220 ui::GestureProvider::Config config = ui::DefaultGestureProviderConfig();
221 config.disable_click_delay =
222 base::CommandLine::ForCurrentProcess()->HasSwitch(
223 switches::kDisableClickDelay);
227 bool HasFixedPageScale(const cc::CompositorFrameMetadata& frame_metadata) {
228 return frame_metadata.min_page_scale_factor ==
229 frame_metadata.max_page_scale_factor;
232 bool HasMobileViewport(const cc::CompositorFrameMetadata& frame_metadata) {
233 float window_width_dip =
234 frame_metadata.page_scale_factor *
235 frame_metadata.scrollable_viewport_size.width();
236 float content_width_css = frame_metadata.root_layer_size.width();
237 return content_width_css <= window_width_dip + kMobileViewportWidthEpsilon;
240 } // anonymous namespace
242 ReadbackRequest::ReadbackRequest(
244 SkColorType color_type,
245 gfx::Rect src_subrect,
246 const base::Callback<void(bool, const SkBitmap&)>& result_callback)
248 color_type_(color_type),
249 src_subrect_(src_subrect),
250 result_callback_(result_callback) {
253 ReadbackRequest::ReadbackRequest() {
256 ReadbackRequest::~ReadbackRequest() {
259 RenderWidgetHostViewAndroid::LastFrameInfo::LastFrameInfo(
261 scoped_ptr<cc::CompositorFrame> output_frame)
262 : output_surface_id(output_id), frame(output_frame.Pass()) {}
264 RenderWidgetHostViewAndroid::LastFrameInfo::~LastFrameInfo() {}
266 RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
267 RenderWidgetHostImpl* widget_host,
268 ContentViewCoreImpl* content_view_core)
269 : host_(widget_host),
270 outstanding_vsync_requests_(0),
271 is_showing_(!widget_host->is_hidden()),
272 content_view_core_(NULL),
273 ime_adapter_android_(this),
274 cached_background_color_(SK_ColorWHITE),
275 last_output_surface_id_(kUndefinedOutputSurfaceId),
276 overscroll_effect_enabled_(
277 !base::CommandLine::ForCurrentProcess()->HasSwitch(
278 switches::kDisableOverscrollEdgeEffect)),
279 gesture_provider_(CreateGestureProviderConfig(), this),
280 gesture_text_selector_(this),
281 accelerated_surface_route_id_(0),
282 using_synchronous_compositor_(SynchronousCompositorImpl::FromID(
283 widget_host->GetProcess()->GetID(),
284 widget_host->GetRoutingID()) != NULL),
285 frame_evictor_(new DelegatedFrameEvictor(this)),
286 locks_on_frame_count_(0),
287 observing_root_window_(false),
288 weak_ptr_factory_(this) {
289 host_->SetView(this);
290 SetContentViewCore(content_view_core);
291 ImageTransportFactoryAndroid::AddObserver(this);
294 RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() {
295 ImageTransportFactoryAndroid::RemoveObserver(this);
296 SetContentViewCore(NULL);
297 DCHECK(ack_callbacks_.empty());
298 DCHECK(readbacks_waiting_for_frame_.empty());
299 if (resource_collection_.get())
300 resource_collection_->SetClient(NULL);
304 bool RenderWidgetHostViewAndroid::OnMessageReceived(
305 const IPC::Message& message) {
307 IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAndroid, message)
308 IPC_MESSAGE_HANDLER(ViewHostMsg_StartContentIntent, OnStartContentIntent)
309 IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeBodyBackgroundColor,
310 OnDidChangeBodyBackgroundColor)
311 IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrame,
312 OnSetNeedsBeginFrame)
313 IPC_MESSAGE_HANDLER(ViewHostMsg_SmartClipDataExtracted,
314 OnSmartClipDataExtracted)
315 IPC_MESSAGE_UNHANDLED(handled = false)
316 IPC_END_MESSAGE_MAP()
320 void RenderWidgetHostViewAndroid::InitAsChild(gfx::NativeView parent_view) {
324 void RenderWidgetHostViewAndroid::InitAsPopup(
325 RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) {
329 void RenderWidgetHostViewAndroid::InitAsFullscreen(
330 RenderWidgetHostView* reference_host_view) {
335 RenderWidgetHostViewAndroid::GetRenderWidgetHost() const {
339 void RenderWidgetHostViewAndroid::WasShown() {
340 if (!host_ || !host_->is_hidden())
343 host_->WasShown(ui::LatencyInfo());
345 if (content_view_core_) {
346 StartObservingRootWindow();
347 RequestVSyncUpdate(BEGIN_FRAME);
351 void RenderWidgetHostViewAndroid::WasHidden() {
354 if (!host_ || host_->is_hidden())
357 // Inform the renderer that we are being hidden so it can reduce its resource
361 StopObservingRootWindow();
364 void RenderWidgetHostViewAndroid::WasResized() {
368 void RenderWidgetHostViewAndroid::SetSize(const gfx::Size& size) {
369 // Ignore the given size as only the Java code has the power to
370 // resize the view on Android.
371 default_size_ = size;
374 void RenderWidgetHostViewAndroid::SetBounds(const gfx::Rect& rect) {
375 SetSize(rect.size());
378 void RenderWidgetHostViewAndroid::AbortPendingReadbackRequests() {
379 while (!readbacks_waiting_for_frame_.empty()) {
380 ReadbackRequest& readback_request = readbacks_waiting_for_frame_.front();
381 readback_request.GetResultCallback().Run(false, SkBitmap());
382 readbacks_waiting_for_frame_.pop();
386 void RenderWidgetHostViewAndroid::GetScaledContentBitmap(
388 SkColorType color_type,
389 gfx::Rect src_subrect,
390 CopyFromCompositingSurfaceCallback& result_callback) {
391 if (!host_ || host_->is_hidden()) {
392 result_callback.Run(false, SkBitmap());
395 if (!IsSurfaceAvailableForCopy()) {
396 // The view is visible, probably the frame has not yet arrived.
397 // Just add the ReadbackRequest to queue and wait for frame arrival
398 // to get this request processed.
399 readbacks_waiting_for_frame_.push(
400 ReadbackRequest(scale, color_type, src_subrect, result_callback));
404 gfx::Size bounds = layer_->bounds();
405 if (src_subrect.IsEmpty())
406 src_subrect = gfx::Rect(bounds);
407 DCHECK_LE(src_subrect.width() + src_subrect.x(), bounds.width());
408 DCHECK_LE(src_subrect.height() + src_subrect.y(), bounds.height());
409 const gfx::Display& display =
410 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
411 float device_scale_factor = display.device_scale_factor();
412 DCHECK_GT(device_scale_factor, 0);
414 gfx::ToCeiledSize(gfx::ScaleSize(bounds, scale / device_scale_factor)));
415 CopyFromCompositingSurface(
416 src_subrect, dst_size, result_callback, color_type);
419 scoped_refptr<cc::DelegatedRendererLayer>
420 RenderWidgetHostViewAndroid::CreateDelegatedLayerForFrameProvider() const {
421 DCHECK(frame_provider_);
423 scoped_refptr<cc::DelegatedRendererLayer> delegated_layer =
424 cc::DelegatedRendererLayer::Create(frame_provider_);
425 delegated_layer->SetBounds(content_size_in_layer_);
426 delegated_layer->SetIsDrawable(true);
427 delegated_layer->SetContentsOpaque(true);
429 return delegated_layer;
432 bool RenderWidgetHostViewAndroid::HasValidFrame() const {
433 if (!content_view_core_)
438 if (texture_size_in_layer_.IsEmpty())
440 // This tell us whether a valid frame has arrived or not.
441 if (!frame_evictor_->HasFrame())
447 gfx::Vector2dF RenderWidgetHostViewAndroid::GetLastScrollOffset() const {
448 return last_scroll_offset_;
451 gfx::NativeView RenderWidgetHostViewAndroid::GetNativeView() const {
452 return content_view_core_->GetViewAndroid();
455 gfx::NativeViewId RenderWidgetHostViewAndroid::GetNativeViewId() const {
456 return reinterpret_cast<gfx::NativeViewId>(
457 const_cast<RenderWidgetHostViewAndroid*>(this));
460 gfx::NativeViewAccessible
461 RenderWidgetHostViewAndroid::GetNativeViewAccessible() {
466 void RenderWidgetHostViewAndroid::MovePluginWindows(
467 const std::vector<WebPluginGeometry>& moves) {
468 // We don't have plugin windows on Android. Do nothing. Note: this is called
469 // from RenderWidgetHost::OnUpdateRect which is itself invoked while
470 // processing the corresponding message from Renderer.
473 void RenderWidgetHostViewAndroid::Focus() {
475 host_->SetInputMethodActive(true);
476 if (overscroll_effect_)
477 overscroll_effect_->Enable();
478 if (selection_controller_)
479 selection_controller_->SetTemporarilyHidden(false);
482 void RenderWidgetHostViewAndroid::Blur() {
483 host_->SetInputMethodActive(false);
485 if (overscroll_effect_)
486 overscroll_effect_->Disable();
487 if (selection_controller_)
488 selection_controller_->SetTemporarilyHidden(true);
491 bool RenderWidgetHostViewAndroid::HasFocus() const {
492 if (!content_view_core_)
493 return false; // ContentViewCore not created yet.
495 return content_view_core_->HasFocus();
498 bool RenderWidgetHostViewAndroid::IsSurfaceAvailableForCopy() const {
499 return HasValidFrame();
502 void RenderWidgetHostViewAndroid::Show() {
508 layer_->SetHideLayerAndSubtree(false);
510 frame_evictor_->SetVisible(true);
514 void RenderWidgetHostViewAndroid::Hide() {
519 if (layer_ && locks_on_frame_count_ == 0)
520 layer_->SetHideLayerAndSubtree(true);
522 frame_evictor_->SetVisible(false);
523 // We don't know if we will ever get a frame if we are hiding the renderer, so
524 // we need to cancel all requests
525 AbortPendingReadbackRequests();
529 bool RenderWidgetHostViewAndroid::IsShowing() {
530 // ContentViewCoreImpl represents the native side of the Java
531 // ContentViewCore. It being NULL means that it is not attached
532 // to the View system yet, so we treat this RWHVA as hidden.
533 return is_showing_ && content_view_core_;
536 void RenderWidgetHostViewAndroid::LockCompositingSurface() {
537 DCHECK(HasValidFrame());
539 DCHECK(frame_evictor_->HasFrame());
540 frame_evictor_->LockFrame();
541 locks_on_frame_count_++;
544 void RenderWidgetHostViewAndroid::UnlockCompositingSurface() {
545 if (!frame_evictor_->HasFrame() || locks_on_frame_count_ == 0)
548 DCHECK(HasValidFrame());
549 frame_evictor_->UnlockFrame();
550 locks_on_frame_count_--;
552 if (locks_on_frame_count_ == 0) {
553 if (last_frame_info_) {
554 InternalSwapCompositorFrame(last_frame_info_->output_surface_id,
555 last_frame_info_->frame.Pass());
556 last_frame_info_.reset();
559 if (!is_showing_ && layer_)
560 layer_->SetHideLayerAndSubtree(true);
564 void RenderWidgetHostViewAndroid::SetTextSurroundingSelectionCallback(
565 const TextSurroundingSelectionCallback& callback) {
566 // Only one outstanding request is allowed at any given time.
567 DCHECK(!callback.is_null());
568 text_surrounding_selection_callback_ = callback;
571 void RenderWidgetHostViewAndroid::OnTextSurroundingSelectionResponse(
572 const base::string16& content,
575 if (text_surrounding_selection_callback_.is_null())
577 text_surrounding_selection_callback_.Run(content, start_offset, end_offset);
578 text_surrounding_selection_callback_.Reset();
581 void RenderWidgetHostViewAndroid::ReleaseLocksOnSurface() {
582 if (!frame_evictor_->HasFrame()) {
583 DCHECK_EQ(locks_on_frame_count_, 0u);
586 while (locks_on_frame_count_ > 0) {
587 UnlockCompositingSurface();
592 gfx::Rect RenderWidgetHostViewAndroid::GetViewBounds() const {
593 if (!content_view_core_)
594 return gfx::Rect(default_size_);
596 return gfx::Rect(content_view_core_->GetViewSize());
599 gfx::Size RenderWidgetHostViewAndroid::GetPhysicalBackingSize() const {
600 if (!content_view_core_)
603 return content_view_core_->GetPhysicalBackingSize();
606 float RenderWidgetHostViewAndroid::GetTopControlsLayoutHeight() const {
607 if (!content_view_core_)
610 // The amount that the viewport size given to Blink is shrunk by the URL-bar.
611 return content_view_core_->GetTopControlsLayoutHeightDip();
614 void RenderWidgetHostViewAndroid::UpdateCursor(const WebCursor& cursor) {
615 // There are no cursors on Android.
618 void RenderWidgetHostViewAndroid::SetIsLoading(bool is_loading) {
619 // Do nothing. The UI notification is handled through ContentViewClient which
620 // is TabContentsDelegate.
623 long RenderWidgetHostViewAndroid::GetNativeImeAdapter() {
624 return reinterpret_cast<intptr_t>(&ime_adapter_android_);
627 void RenderWidgetHostViewAndroid::TextInputStateChanged(
628 const ViewHostMsg_TextInputState_Params& params) {
629 if (selection_controller_) {
630 // This call is semi-redundant with that in |OnFocusedNodeChanged|. The
631 // latter is guaranteed to be called before |OnSelectionBoundsChanged|,
632 // while this call is present to ensure consistency with IME after
633 // navigation and tab focus changes
634 const bool is_editable_node = params.type != ui::TEXT_INPUT_TYPE_NONE;
635 selection_controller_->OnSelectionEditable(is_editable_node);
638 // If the change is not originated from IME (e.g. Javascript, autofill),
639 // send back the renderer an acknowledgement, regardless of how we exit from
641 base::ScopedClosureRunner ack_caller;
642 if (params.is_non_ime_change)
643 ack_caller.Reset(base::Bind(&SendImeEventAck, host_));
648 content_view_core_->UpdateImeAdapter(
649 GetNativeImeAdapter(),
650 static_cast<int>(params.type), params.flags,
651 params.value, params.selection_start, params.selection_end,
652 params.composition_start, params.composition_end,
653 params.show_ime_if_needed, params.is_non_ime_change);
656 void RenderWidgetHostViewAndroid::OnDidChangeBodyBackgroundColor(
658 if (cached_background_color_ == color)
661 cached_background_color_ = color;
662 if (content_view_core_)
663 content_view_core_->OnBackgroundColorChanged(color);
666 void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame(bool enabled) {
667 DCHECK(!using_synchronous_compositor_);
668 TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame",
671 RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME);
673 outstanding_vsync_requests_ &= ~PERSISTENT_BEGIN_FRAME;
676 void RenderWidgetHostViewAndroid::OnStartContentIntent(
677 const GURL& content_url) {
678 if (content_view_core_)
679 content_view_core_->StartContentIntent(content_url);
682 void RenderWidgetHostViewAndroid::OnSmartClipDataExtracted(
683 const base::string16& text,
684 const base::string16& html,
685 const gfx::Rect rect) {
686 if (content_view_core_)
687 content_view_core_->OnSmartClipDataExtracted(text, html, rect);
690 bool RenderWidgetHostViewAndroid::OnTouchEvent(
691 const ui::MotionEvent& event) {
695 if (selection_controller_ &&
696 selection_controller_->WillHandleTouchEvent(event))
699 if (!gesture_provider_.OnTouchEvent(event))
702 if (gesture_text_selector_.OnTouchEvent(event)) {
703 gesture_provider_.OnTouchEventAck(false);
707 if (host_->ShouldForwardTouchEvent()) {
708 blink::WebTouchEvent web_event = CreateWebTouchEventFromMotionEvent(event);
709 host_->ForwardTouchEventWithLatencyInfo(web_event,
710 CreateLatencyInfo(web_event));
712 const bool event_consumed = false;
713 gesture_provider_.OnTouchEventAck(event_consumed);
716 // Send a proactive BeginFrame on the next vsync to reduce latency.
717 // This is good enough as long as the first touch event has Begin semantics
718 // and the actual scroll happens on the next vsync.
719 if (observing_root_window_)
720 RequestVSyncUpdate(BEGIN_FRAME);
725 bool RenderWidgetHostViewAndroid::OnTouchHandleEvent(
726 const ui::MotionEvent& event) {
727 return selection_controller_ &&
728 selection_controller_->WillHandleTouchEvent(event);
731 void RenderWidgetHostViewAndroid::ResetGestureDetection() {
732 const ui::MotionEvent* current_down_event =
733 gesture_provider_.GetCurrentDownEvent();
734 if (!current_down_event)
737 scoped_ptr<ui::MotionEvent> cancel_event = current_down_event->Cancel();
738 DCHECK(cancel_event);
739 OnTouchEvent(*cancel_event);
742 void RenderWidgetHostViewAndroid::SetDoubleTapSupportEnabled(bool enabled) {
743 gesture_provider_.SetDoubleTapSupportForPlatformEnabled(enabled);
746 void RenderWidgetHostViewAndroid::SetMultiTouchZoomSupportEnabled(
748 gesture_provider_.SetMultiTouchZoomSupportEnabled(enabled);
751 void RenderWidgetHostViewAndroid::ImeCancelComposition() {
752 ime_adapter_android_.CancelComposition();
755 void RenderWidgetHostViewAndroid::FocusedNodeChanged(bool is_editable_node) {
756 ime_adapter_android_.FocusedNodeChanged(is_editable_node);
757 if (selection_controller_)
758 selection_controller_->OnSelectionEditable(is_editable_node);
761 void RenderWidgetHostViewAndroid::RenderProcessGone(
762 base::TerminationStatus status, int error_code) {
766 void RenderWidgetHostViewAndroid::Destroy() {
768 SetContentViewCore(NULL);
770 // The RenderWidgetHost's destruction led here, so don't call it.
776 void RenderWidgetHostViewAndroid::SetTooltipText(
777 const base::string16& tooltip_text) {
778 // Tooltips don't makes sense on Android.
781 void RenderWidgetHostViewAndroid::SelectionChanged(const base::string16& text,
783 const gfx::Range& range) {
784 RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
786 if (selection_controller_)
787 selection_controller_->OnSelectionEmpty(text.empty());
789 if (!content_view_core_)
791 if (range.is_empty()) {
792 content_view_core_->OnSelectionChanged("");
796 DCHECK(!text.empty());
797 size_t pos = range.GetMin() - offset;
798 size_t n = range.length();
800 DCHECK(pos + n <= text.length()) << "The text can not fully cover range.";
801 if (pos >= text.length()) {
802 NOTREACHED() << "The text can not cover range.";
806 std::string utf8_selection = base::UTF16ToUTF8(text.substr(pos, n));
808 content_view_core_->OnSelectionChanged(utf8_selection);
811 void RenderWidgetHostViewAndroid::SelectionBoundsChanged(
812 const ViewHostMsg_SelectionBounds_Params& params) {
813 NOTREACHED() << "Selection bounds should be routed through the compositor.";
816 void RenderWidgetHostViewAndroid::SetBackgroundOpaque(bool opaque) {
817 RenderWidgetHostViewBase::SetBackgroundOpaque(opaque);
818 host_->SetBackgroundOpaque(opaque);
821 void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
822 const gfx::Rect& src_subrect,
823 const gfx::Size& dst_size,
824 CopyFromCompositingSurfaceCallback& callback,
825 const SkColorType color_type) {
826 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurface");
827 if ((!host_ || host_->is_hidden()) ||
828 !IsReadbackConfigSupported(color_type)) {
829 callback.Run(false, SkBitmap());
832 base::TimeTicks start_time = base::TimeTicks::Now();
833 if (!using_synchronous_compositor_ && !IsSurfaceAvailableForCopy()) {
834 callback.Run(false, SkBitmap());
837 const gfx::Display& display =
838 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
839 float device_scale_factor = display.device_scale_factor();
840 gfx::Size dst_size_in_pixel =
841 ConvertRectToPixel(device_scale_factor, gfx::Rect(dst_size)).size();
842 gfx::Rect src_subrect_in_pixel =
843 ConvertRectToPixel(device_scale_factor, src_subrect);
845 if (using_synchronous_compositor_) {
846 SynchronousCopyContents(src_subrect_in_pixel, dst_size_in_pixel, callback,
848 UMA_HISTOGRAM_TIMES("Compositing.CopyFromSurfaceTimeSynchronous",
849 base::TimeTicks::Now() - start_time);
853 scoped_ptr<cc::CopyOutputRequest> request;
854 scoped_refptr<cc::Layer> readback_layer;
855 DCHECK(content_view_core_);
856 DCHECK(content_view_core_->GetWindowAndroid());
857 ui::WindowAndroidCompositor* compositor =
858 content_view_core_->GetWindowAndroid()->GetCompositor();
860 DCHECK(frame_provider_);
861 scoped_refptr<cc::DelegatedRendererLayer> delegated_layer =
862 CreateDelegatedLayerForFrameProvider();
863 delegated_layer->SetHideLayerAndSubtree(true);
864 compositor->AttachLayerForReadback(delegated_layer);
866 readback_layer = delegated_layer;
867 request = cc::CopyOutputRequest::CreateRequest(
868 base::Bind(&RenderWidgetHostViewAndroid::
869 PrepareTextureCopyOutputResultForDelegatedReadback,
875 request->set_area(src_subrect_in_pixel);
876 readback_layer->RequestCopyOfOutput(request.Pass());
879 void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame(
880 const gfx::Rect& src_subrect,
881 const scoped_refptr<media::VideoFrame>& target,
882 const base::Callback<void(bool)>& callback) {
887 bool RenderWidgetHostViewAndroid::CanCopyToVideoFrame() const {
891 void RenderWidgetHostViewAndroid::ShowDisambiguationPopup(
892 const gfx::Rect& rect_pixels, const SkBitmap& zoomed_bitmap) {
893 if (!content_view_core_)
896 content_view_core_->ShowDisambiguationPopup(rect_pixels, zoomed_bitmap);
899 scoped_ptr<SyntheticGestureTarget>
900 RenderWidgetHostViewAndroid::CreateSyntheticGestureTarget() {
901 return scoped_ptr<SyntheticGestureTarget>(new SyntheticGestureTargetAndroid(
902 host_, content_view_core_->CreateTouchEventSynthesizer()));
905 void RenderWidgetHostViewAndroid::SendDelegatedFrameAck(
906 uint32 output_surface_id) {
908 cc::CompositorFrameAck ack;
909 if (resource_collection_.get())
910 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
911 RenderWidgetHostImpl::SendSwapCompositorFrameAck(host_->GetRoutingID(),
913 host_->GetProcess()->GetID(),
917 void RenderWidgetHostViewAndroid::SendReturnedDelegatedResources(
918 uint32 output_surface_id) {
919 DCHECK(resource_collection_);
921 cc::CompositorFrameAck ack;
922 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
923 DCHECK(!ack.resources.empty());
925 RenderWidgetHostImpl::SendReclaimCompositorResources(
926 host_->GetRoutingID(),
928 host_->GetProcess()->GetID(),
932 void RenderWidgetHostViewAndroid::UnusedResourcesAreAvailable() {
933 if (ack_callbacks_.size())
935 SendReturnedDelegatedResources(last_output_surface_id_);
938 void RenderWidgetHostViewAndroid::DestroyDelegatedContent() {
940 frame_provider_ = NULL;
942 // This gets called when ever any eviction, loosing resources, swapping
943 // problems are encountered and so we abort any pending readbacks here.
944 AbortPendingReadbackRequests();
947 void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
948 uint32 output_surface_id,
949 scoped_ptr<cc::DelegatedFrameData> frame_data) {
950 bool has_content = !texture_size_in_layer_.IsEmpty();
952 if (output_surface_id != last_output_surface_id_) {
953 // Drop the cc::DelegatedFrameResourceCollection so that we will not return
954 // any resources from the old output surface with the new output surface id.
955 if (resource_collection_.get()) {
956 resource_collection_->SetClient(NULL);
957 if (resource_collection_->LoseAllResources())
958 SendReturnedDelegatedResources(last_output_surface_id_);
959 resource_collection_ = NULL;
961 DestroyDelegatedContent();
963 last_output_surface_id_ = output_surface_id;
966 // DelegatedRendererLayerImpl applies the inverse device_scale_factor of the
967 // renderer frame, assuming that the browser compositor will scale
968 // it back up to device scale. But on Android we put our browser layers in
969 // physical pixels and set our browser CC device_scale_factor to 1, so this
970 // suppresses the transform. This line may need to be removed when fixing
971 // http://crbug.com/384134 or http://crbug.com/310763
972 frame_data->device_scale_factor = 1.0f;
975 DestroyDelegatedContent();
977 if (!resource_collection_.get()) {
978 resource_collection_ = new cc::DelegatedFrameResourceCollection;
979 resource_collection_->SetClient(this);
981 if (!frame_provider_ ||
982 texture_size_in_layer_ != frame_provider_->frame_size()) {
984 frame_provider_ = new cc::DelegatedFrameProvider(
985 resource_collection_.get(), frame_data.Pass());
986 layer_ = cc::DelegatedRendererLayer::Create(frame_provider_);
989 frame_provider_->SetFrameData(frame_data.Pass());
994 layer_->SetIsDrawable(true);
995 layer_->SetContentsOpaque(true);
996 layer_->SetBounds(content_size_in_layer_);
997 layer_->SetNeedsDisplay();
1000 base::Closure ack_callback =
1001 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck,
1002 weak_ptr_factory_.GetWeakPtr(),
1005 ack_callbacks_.push(ack_callback);
1006 if (host_->is_hidden())
1010 void RenderWidgetHostViewAndroid::ComputeContentsSize(
1011 const cc::CompositorFrameMetadata& frame_metadata) {
1012 // Calculate the content size. This should be 0 if the texture_size is 0.
1013 gfx::Vector2dF offset;
1014 if (texture_size_in_layer_.IsEmpty())
1015 content_size_in_layer_ = gfx::Size();
1016 content_size_in_layer_ = gfx::ToCeiledSize(gfx::ScaleSize(
1017 frame_metadata.scrollable_viewport_size,
1018 frame_metadata.device_scale_factor * frame_metadata.page_scale_factor));
1020 if (overscroll_effect_) {
1021 overscroll_effect_->UpdateDisplayParameters(
1022 CreateOverscrollDisplayParameters(frame_metadata));
1026 void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame(
1027 uint32 output_surface_id,
1028 scoped_ptr<cc::CompositorFrame> frame) {
1029 last_scroll_offset_ = frame->metadata.root_scroll_offset;
1030 if (!frame->delegated_frame_data) {
1031 LOG(ERROR) << "Non-delegated renderer path no longer supported";
1035 if (locks_on_frame_count_ > 0) {
1036 DCHECK(HasValidFrame());
1037 RetainFrame(output_surface_id, frame.Pass());
1041 if (layer_ && layer_->layer_tree_host()) {
1042 for (size_t i = 0; i < frame->metadata.latency_info.size(); i++) {
1043 scoped_ptr<cc::SwapPromise> swap_promise(
1044 new cc::LatencyInfoSwapPromise(frame->metadata.latency_info[i]));
1045 layer_->layer_tree_host()->QueueSwapPromise(swap_promise.Pass());
1049 DCHECK(!frame->delegated_frame_data->render_pass_list.empty());
1051 cc::RenderPass* root_pass =
1052 frame->delegated_frame_data->render_pass_list.back();
1053 texture_size_in_layer_ = root_pass->output_rect.size();
1054 ComputeContentsSize(frame->metadata);
1056 SwapDelegatedFrame(output_surface_id, frame->delegated_frame_data.Pass());
1057 frame_evictor_->SwappedFrame(!host_->is_hidden());
1059 // As the metadata update may trigger view invalidation, always call it after
1060 // any potential compositor scheduling.
1061 OnFrameMetadataUpdated(frame->metadata);
1062 // Check if we have any pending readbacks, see if we have a frame available
1063 // and process them here.
1064 if (!readbacks_waiting_for_frame_.empty()) {
1065 while (!readbacks_waiting_for_frame_.empty()) {
1066 ReadbackRequest& readback_request = readbacks_waiting_for_frame_.front();
1067 GetScaledContentBitmap(readback_request.GetScale(),
1068 readback_request.GetColorFormat(),
1069 readback_request.GetCaptureRect(),
1070 readback_request.GetResultCallback());
1071 readbacks_waiting_for_frame_.pop();
1076 void RenderWidgetHostViewAndroid::OnSwapCompositorFrame(
1077 uint32 output_surface_id,
1078 scoped_ptr<cc::CompositorFrame> frame) {
1079 InternalSwapCompositorFrame(output_surface_id, frame.Pass());
1082 void RenderWidgetHostViewAndroid::RetainFrame(
1083 uint32 output_surface_id,
1084 scoped_ptr<cc::CompositorFrame> frame) {
1085 DCHECK(locks_on_frame_count_);
1087 // Store the incoming frame so that it can be swapped when all the locks have
1088 // been released. If there is already a stored frame, then replace and skip
1089 // the previous one but make sure we still eventually send the ACK. Holding
1090 // the ACK also blocks the renderer when its max_frames_pending is reached.
1091 if (last_frame_info_) {
1092 base::Closure ack_callback =
1093 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck,
1094 weak_ptr_factory_.GetWeakPtr(),
1095 last_frame_info_->output_surface_id);
1097 ack_callbacks_.push(ack_callback);
1100 last_frame_info_.reset(new LastFrameInfo(output_surface_id, frame.Pass()));
1103 void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
1104 const cc::CompositorFrameMetadata& frame_metadata) {
1105 // This is a subset of OnSwapCompositorFrame() used in the synchronous
1107 OnFrameMetadataUpdated(frame_metadata);
1108 ComputeContentsSize(frame_metadata);
1110 // DevTools ScreenCast support for Android WebView.
1111 WebContents* web_contents = content_view_core_->GetWebContents();
1112 if (DevToolsAgentHost::HasFor(web_contents)) {
1113 scoped_refptr<DevToolsAgentHost> dtah =
1114 DevToolsAgentHost::GetOrCreateFor(web_contents);
1115 // Unblock the compositor.
1116 BrowserThread::PostTask(
1117 BrowserThread::UI, FROM_HERE,
1118 base::Bind(&RenderViewDevToolsAgentHost::SynchronousSwapCompositorFrame,
1119 static_cast<RenderViewDevToolsAgentHost*>(dtah.get()),
1124 void RenderWidgetHostViewAndroid::SetOverlayVideoMode(bool enabled) {
1126 layer_->SetContentsOpaque(!enabled);
1129 bool RenderWidgetHostViewAndroid::SupportsAnimation() const {
1130 // The synchronous (WebView) compositor does not have a proper browser
1131 // compositor with which to drive animations.
1132 return !using_synchronous_compositor_;
1135 void RenderWidgetHostViewAndroid::SetNeedsAnimate() {
1136 DCHECK(content_view_core_);
1137 DCHECK(!using_synchronous_compositor_);
1138 content_view_core_->GetWindowAndroid()->SetNeedsAnimate();
1141 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::PointF& position) {
1142 MoveCaret(gfx::Point(position.x(), position.y()));
1145 void RenderWidgetHostViewAndroid::SelectBetweenCoordinates(
1146 const gfx::PointF& start,
1147 const gfx::PointF& end) {
1148 DCHECK(content_view_core_);
1149 content_view_core_->SelectBetweenCoordinates(start, end);
1152 void RenderWidgetHostViewAndroid::OnSelectionEvent(
1153 SelectionEventType event,
1154 const gfx::PointF& position) {
1155 DCHECK(content_view_core_);
1156 content_view_core_->OnSelectionEvent(event, position);
1159 scoped_ptr<TouchHandleDrawable> RenderWidgetHostViewAndroid::CreateDrawable() {
1160 DCHECK(content_view_core_);
1161 if (using_synchronous_compositor_)
1162 return content_view_core_->CreatePopupTouchHandleDrawable();
1164 return scoped_ptr<TouchHandleDrawable>(new CompositedTouchHandleDrawable(
1165 content_view_core_->GetLayer(),
1166 content_view_core_->GetDpiScale(),
1167 base::android::GetApplicationContext()));
1170 void RenderWidgetHostViewAndroid::SynchronousCopyContents(
1171 const gfx::Rect& src_subrect_in_pixel,
1172 const gfx::Size& dst_size_in_pixel,
1173 const base::Callback<void(bool, const SkBitmap&)>& callback,
1174 const SkColorType color_type) {
1175 SynchronousCompositor* compositor =
1176 SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
1177 host_->GetRoutingID());
1179 callback.Run(false, SkBitmap());
1184 bitmap.allocPixels(SkImageInfo::Make(dst_size_in_pixel.width(),
1185 dst_size_in_pixel.height(),
1187 kPremul_SkAlphaType));
1188 SkCanvas canvas(bitmap);
1190 (float)dst_size_in_pixel.width() / (float)src_subrect_in_pixel.width(),
1191 (float)dst_size_in_pixel.height() / (float)src_subrect_in_pixel.height());
1192 compositor->DemandDrawSw(&canvas);
1193 callback.Run(true, bitmap);
1196 void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
1197 const cc::CompositorFrameMetadata& frame_metadata) {
1199 // Disable double tap zoom for pages that have a width=device-width or
1200 // narrower viewport (indicating that this is a mobile-optimized or responsive
1201 // web design, so text will be legible without zooming). Also disable
1202 // double tap and pinch for pages that prevent zooming in or out.
1203 bool has_mobile_viewport = HasMobileViewport(frame_metadata);
1204 bool has_fixed_page_scale = HasFixedPageScale(frame_metadata);
1205 gesture_provider_.SetDoubleTapSupportForPageEnabled(
1206 !has_fixed_page_scale && !has_mobile_viewport);
1208 if (!content_view_core_)
1211 DCHECK(selection_controller_);
1212 selection_controller_->OnSelectionBoundsChanged(
1213 frame_metadata.selection_start, frame_metadata.selection_end);
1215 // All offsets and sizes are in CSS pixels.
1216 content_view_core_->UpdateFrameInfo(
1217 frame_metadata.root_scroll_offset,
1218 frame_metadata.page_scale_factor,
1219 gfx::Vector2dF(frame_metadata.min_page_scale_factor,
1220 frame_metadata.max_page_scale_factor),
1221 frame_metadata.root_layer_size,
1222 frame_metadata.scrollable_viewport_size,
1223 frame_metadata.location_bar_offset,
1224 frame_metadata.location_bar_content_translation);
1225 #if defined(VIDEO_HOLE)
1226 if (host_ && host_->IsRenderView()) {
1227 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
1228 RenderViewHost::From(host_));
1229 rvhi->media_web_contents_observer()->OnFrameInfoUpdated();
1231 #endif // defined(VIDEO_HOLE)
1234 void RenderWidgetHostViewAndroid::AcceleratedSurfaceInitialized(int host_id,
1236 accelerated_surface_route_id_ = route_id;
1239 void RenderWidgetHostViewAndroid::AcceleratedSurfaceBuffersSwapped(
1240 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
1242 NOTREACHED() << "Need --composite-to-mailbox or --enable-delegated-renderer";
1245 void RenderWidgetHostViewAndroid::AttachLayers() {
1246 if (!content_view_core_)
1251 content_view_core_->AttachLayer(layer_);
1252 if (overscroll_effect_)
1253 overscroll_effect_->Enable();
1254 layer_->SetHideLayerAndSubtree(!is_showing_);
1257 void RenderWidgetHostViewAndroid::RemoveLayers() {
1258 if (!content_view_core_)
1264 content_view_core_->RemoveLayer(layer_);
1265 if (overscroll_effect_)
1266 overscroll_effect_->Disable();
1269 void RenderWidgetHostViewAndroid::RequestVSyncUpdate(uint32 requests) {
1270 // The synchronous compositor does not requre BeginFrame messages.
1271 if (using_synchronous_compositor_)
1272 requests &= FLUSH_INPUT;
1274 bool should_request_vsync = !outstanding_vsync_requests_ && requests;
1275 outstanding_vsync_requests_ |= requests;
1276 // Note that if we're not currently observing the root window, outstanding
1277 // vsync requests will be pushed if/when we resume observing in
1278 // |StartObservingRootWindow()|.
1279 if (observing_root_window_ && should_request_vsync)
1280 content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
1283 void RenderWidgetHostViewAndroid::StartObservingRootWindow() {
1284 DCHECK(content_view_core_);
1285 if (observing_root_window_)
1288 observing_root_window_ = true;
1289 content_view_core_->GetWindowAndroid()->AddObserver(this);
1291 // Clear existing vsync requests to allow a request to the new window.
1292 uint32 outstanding_vsync_requests = outstanding_vsync_requests_;
1293 outstanding_vsync_requests_ = 0;
1294 RequestVSyncUpdate(outstanding_vsync_requests);
1297 void RenderWidgetHostViewAndroid::StopObservingRootWindow() {
1298 if (!content_view_core_) {
1299 DCHECK(!observing_root_window_);
1303 if (!observing_root_window_)
1306 observing_root_window_ = false;
1307 content_view_core_->GetWindowAndroid()->RemoveObserver(this);
1310 void RenderWidgetHostViewAndroid::SendBeginFrame(base::TimeTicks frame_time,
1311 base::TimeDelta vsync_period) {
1312 TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::SendBeginFrame",
1313 "frame_time_us", frame_time.ToInternalValue());
1314 base::TimeTicks display_time = frame_time + vsync_period;
1316 // TODO(brianderson): Use adaptive draw-time estimation.
1317 base::TimeDelta estimated_browser_composite_time =
1318 base::TimeDelta::FromMicroseconds(
1319 (1.0f * base::Time::kMicrosecondsPerSecond) / (3.0f * 60));
1321 base::TimeTicks deadline = display_time - estimated_browser_composite_time;
1323 host_->Send(new ViewMsg_BeginFrame(
1324 host_->GetRoutingID(),
1325 cc::BeginFrameArgs::Create(frame_time, deadline, vsync_period)));
1328 bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) {
1329 bool needs_animate =
1330 overscroll_effect_ ? overscroll_effect_->Animate(frame_time) : false;
1331 if (selection_controller_)
1332 needs_animate |= selection_controller_->Animate(frame_time);
1333 return needs_animate;
1336 void RenderWidgetHostViewAndroid::AcceleratedSurfacePostSubBuffer(
1337 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
1342 void RenderWidgetHostViewAndroid::AcceleratedSurfaceSuspend() {
1346 void RenderWidgetHostViewAndroid::AcceleratedSurfaceRelease() {
1350 void RenderWidgetHostViewAndroid::EvictDelegatedFrame() {
1352 DestroyDelegatedContent();
1353 frame_evictor_->DiscardedFrame();
1354 // We are evicting the delegated frame,
1355 // so there should be no pending readback requests
1356 DCHECK(readbacks_waiting_for_frame_.empty());
1359 bool RenderWidgetHostViewAndroid::HasAcceleratedSurface(
1360 const gfx::Size& desired_size) {
1365 void RenderWidgetHostViewAndroid::GetScreenInfo(blink::WebScreenInfo* result) {
1366 // ScreenInfo isn't tied to the widget on Android. Always return the default.
1367 RenderWidgetHostViewBase::GetDefaultScreenInfo(result);
1370 // TODO(jrg): Find out the implications and answer correctly here,
1371 // as we are returning the WebView and not root window bounds.
1372 gfx::Rect RenderWidgetHostViewAndroid::GetBoundsInRootWindow() {
1373 return GetViewBounds();
1376 gfx::GLSurfaceHandle RenderWidgetHostViewAndroid::GetCompositingSurface() {
1377 gfx::GLSurfaceHandle handle =
1378 gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NATIVE_TRANSPORT);
1379 if (CompositorImpl::IsInitialized()) {
1380 handle.parent_client_id =
1381 ImageTransportFactoryAndroid::GetInstance()->GetChannelID();
1386 void RenderWidgetHostViewAndroid::ProcessAckedTouchEvent(
1387 const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
1388 const bool event_consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
1389 gesture_provider_.OnTouchEventAck(event_consumed);
1392 void RenderWidgetHostViewAndroid::GestureEventAck(
1393 const blink::WebGestureEvent& event,
1394 InputEventAckState ack_result) {
1395 // The overscroll effect requires an explicit release signal that may not be
1396 // sent from the renderer compositor.
1397 if (event.type == blink::WebInputEvent::GestureScrollEnd ||
1398 event.type == blink::WebInputEvent::GestureFlingStart) {
1399 DidOverscroll(DidOverscrollParams());
1402 if (content_view_core_)
1403 content_view_core_->OnGestureEventAck(event, ack_result);
1406 InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
1407 const blink::WebInputEvent& input_event) {
1408 if (selection_controller_) {
1409 switch (input_event.type) {
1410 case blink::WebInputEvent::GestureLongPress:
1411 selection_controller_->OnLongPressEvent();
1413 case blink::WebInputEvent::GestureTap:
1414 selection_controller_->OnTapEvent();
1421 if (content_view_core_ &&
1422 content_view_core_->FilterInputEvent(input_event))
1423 return INPUT_EVENT_ACK_STATE_CONSUMED;
1426 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1428 if (input_event.type == blink::WebInputEvent::GestureTapDown ||
1429 input_event.type == blink::WebInputEvent::TouchStart) {
1430 GpuDataManagerImpl* gpu_data = GpuDataManagerImpl::GetInstance();
1431 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance();
1432 if (shim && gpu_data && accelerated_surface_route_id_ &&
1433 gpu_data->IsDriverBugWorkaroundActive(gpu::WAKE_UP_GPU_BEFORE_DRAWING))
1435 new AcceleratedSurfaceMsg_WakeUpGpu(accelerated_surface_route_id_));
1438 SynchronousCompositorImpl* compositor =
1439 SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
1440 host_->GetRoutingID());
1442 return compositor->HandleInputEvent(input_event);
1443 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1446 void RenderWidgetHostViewAndroid::OnSetNeedsFlushInput() {
1447 TRACE_EVENT0("input", "RenderWidgetHostViewAndroid::OnSetNeedsFlushInput");
1448 RequestVSyncUpdate(FLUSH_INPUT);
1451 BrowserAccessibilityManager*
1452 RenderWidgetHostViewAndroid::CreateBrowserAccessibilityManager(
1453 BrowserAccessibilityDelegate* delegate) {
1454 base::android::ScopedJavaLocalRef<jobject> obj;
1455 if (content_view_core_)
1456 obj = content_view_core_->GetJavaObject();
1457 return new BrowserAccessibilityManagerAndroid(
1459 BrowserAccessibilityManagerAndroid::GetEmptyDocument(),
1463 bool RenderWidgetHostViewAndroid::LockMouse() {
1468 void RenderWidgetHostViewAndroid::UnlockMouse() {
1472 // Methods called from the host to the render
1474 void RenderWidgetHostViewAndroid::SendKeyEvent(
1475 const NativeWebKeyboardEvent& event) {
1477 host_->ForwardKeyboardEvent(event);
1480 void RenderWidgetHostViewAndroid::SendMouseEvent(
1481 const blink::WebMouseEvent& event) {
1483 host_->ForwardMouseEvent(event);
1486 void RenderWidgetHostViewAndroid::SendMouseWheelEvent(
1487 const blink::WebMouseWheelEvent& event) {
1489 host_->ForwardWheelEvent(event);
1492 void RenderWidgetHostViewAndroid::SendGestureEvent(
1493 const blink::WebGestureEvent& event) {
1494 // Sending a gesture that may trigger overscroll should resume the effect.
1495 if (overscroll_effect_)
1496 overscroll_effect_->Enable();
1499 host_->ForwardGestureEventWithLatencyInfo(event, CreateLatencyInfo(event));
1502 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point& point) {
1504 host_->MoveCaret(point);
1507 void RenderWidgetHostViewAndroid::HideTextHandles() {
1508 if (selection_controller_)
1509 selection_controller_->HideAndDisallowShowingAutomatically();
1512 void RenderWidgetHostViewAndroid::OnShowingPastePopup(
1513 const gfx::PointF& point) {
1514 if (!selection_controller_)
1517 // As the paste popup may be triggered *before* the bounds and editability
1518 // of the region have been updated, explicitly set the properties now.
1519 // TODO(jdduke): Remove this workaround when auxiliary paste popup
1520 // notifications are no longer required, crbug.com/398170.
1521 cc::ViewportSelectionBound insertion_bound;
1522 insertion_bound.type = cc::SELECTION_BOUND_CENTER;
1523 insertion_bound.visible = true;
1524 insertion_bound.edge_top = point;
1525 insertion_bound.edge_bottom = point;
1527 ShowSelectionHandlesAutomatically();
1528 selection_controller_->OnSelectionEditable(true);
1529 selection_controller_->OnSelectionEmpty(true);
1530 selection_controller_->OnSelectionBoundsChanged(insertion_bound,
1534 SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const {
1535 return cached_background_color_;
1538 void RenderWidgetHostViewAndroid::DidOverscroll(
1539 const DidOverscrollParams& params) {
1540 if (!content_view_core_ || !layer_ || !is_showing_)
1543 const float device_scale_factor = content_view_core_->GetDpiScale();
1545 if (overscroll_effect_ &&
1546 overscroll_effect_->OnOverscrolled(
1547 content_view_core_->GetLayer(),
1548 base::TimeTicks::Now(),
1549 gfx::ScaleVector2d(params.accumulated_overscroll,
1550 device_scale_factor),
1551 gfx::ScaleVector2d(params.latest_overscroll_delta,
1552 device_scale_factor),
1553 gfx::ScaleVector2d(params.current_fling_velocity,
1554 device_scale_factor),
1556 params.causal_event_viewport_point.OffsetFromOrigin(),
1557 device_scale_factor))) {
1562 void RenderWidgetHostViewAndroid::DidStopFlinging() {
1563 if (content_view_core_)
1564 content_view_core_->DidStopFlinging();
1567 void RenderWidgetHostViewAndroid::SetContentViewCore(
1568 ContentViewCoreImpl* content_view_core) {
1570 StopObservingRootWindow();
1572 bool resize = false;
1573 if (content_view_core != content_view_core_) {
1574 overscroll_effect_.reset();
1575 selection_controller_.reset();
1576 ReleaseLocksOnSurface();
1580 content_view_core_ = content_view_core;
1582 BrowserAccessibilityManager* manager = NULL;
1584 manager = host_->GetRootBrowserAccessibilityManager();
1586 base::android::ScopedJavaLocalRef<jobject> obj;
1587 if (content_view_core_)
1588 obj = content_view_core_->GetJavaObject();
1589 manager->ToBrowserAccessibilityManagerAndroid()->SetContentViewCore(obj);
1594 if (!content_view_core_)
1597 StartObservingRootWindow();
1602 if (!selection_controller_)
1603 selection_controller_ = CreateSelectionController(this, content_view_core_);
1605 if (overscroll_effect_enabled_ && !overscroll_effect_ &&
1606 content_view_core_->GetWindowAndroid()->GetCompositor())
1607 overscroll_effect_ = CreateOverscrollEffect(content_view_core_);
1610 void RenderWidgetHostViewAndroid::RunAckCallbacks() {
1611 while (!ack_callbacks_.empty()) {
1612 ack_callbacks_.front().Run();
1613 ack_callbacks_.pop();
1617 void RenderWidgetHostViewAndroid::OnGestureEvent(
1618 const ui::GestureEventData& gesture) {
1619 if (gesture_text_selector_.OnGestureEvent(gesture))
1622 SendGestureEvent(CreateWebGestureEventFromGestureEventData(gesture));
1625 void RenderWidgetHostViewAndroid::OnCompositingDidCommit() {
1630 void RenderWidgetHostViewAndroid::OnAttachCompositor() {
1631 DCHECK(content_view_core_);
1632 if (overscroll_effect_enabled_ && !overscroll_effect_)
1633 overscroll_effect_ = CreateOverscrollEffect(content_view_core_);
1636 void RenderWidgetHostViewAndroid::OnDetachCompositor() {
1637 DCHECK(content_view_core_);
1638 DCHECK(!using_synchronous_compositor_);
1640 overscroll_effect_.reset();
1643 void RenderWidgetHostViewAndroid::OnVSync(base::TimeTicks frame_time,
1644 base::TimeDelta vsync_period) {
1645 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::OnVSync");
1649 const uint32 current_vsync_requests = outstanding_vsync_requests_;
1650 outstanding_vsync_requests_ = 0;
1652 if (current_vsync_requests & FLUSH_INPUT)
1653 host_->FlushInput();
1655 if (current_vsync_requests & BEGIN_FRAME ||
1656 current_vsync_requests & PERSISTENT_BEGIN_FRAME) {
1657 SendBeginFrame(frame_time, vsync_period);
1660 if (current_vsync_requests & PERSISTENT_BEGIN_FRAME)
1661 RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME);
1664 void RenderWidgetHostViewAndroid::OnAnimate(base::TimeTicks begin_frame_time) {
1665 if (Animate(begin_frame_time))
1669 void RenderWidgetHostViewAndroid::OnLostResources() {
1670 ReleaseLocksOnSurface();
1672 DestroyDelegatedContent();
1673 DCHECK(ack_callbacks_.empty());
1674 // We should not loose a frame if we have readback requests pending.
1675 DCHECK(readbacks_waiting_for_frame_.empty());
1680 RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResultForDelegatedReadback(
1681 const gfx::Size& dst_size_in_pixel,
1682 const SkColorType color_type,
1683 const base::TimeTicks& start_time,
1684 scoped_refptr<cc::Layer> readback_layer,
1685 const base::Callback<void(bool, const SkBitmap&)>& callback,
1686 scoped_ptr<cc::CopyOutputResult> result) {
1687 readback_layer->RemoveFromParent();
1688 PrepareTextureCopyOutputResult(
1689 dst_size_in_pixel, color_type, start_time, callback, result.Pass());
1693 void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
1694 const gfx::Size& dst_size_in_pixel,
1695 const SkColorType color_type,
1696 const base::TimeTicks& start_time,
1697 const base::Callback<void(bool, const SkBitmap&)>& callback,
1698 scoped_ptr<cc::CopyOutputResult> result) {
1699 base::ScopedClosureRunner scoped_callback_runner(
1700 base::Bind(callback, false, SkBitmap()));
1702 "RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult");
1704 if (!result->HasTexture() || result->IsEmpty() || result->size().IsEmpty())
1707 scoped_ptr<SkBitmap> bitmap(new SkBitmap);
1708 if (!bitmap->tryAllocPixels(SkImageInfo::Make(dst_size_in_pixel.width(),
1709 dst_size_in_pixel.height(),
1711 kOpaque_SkAlphaType)))
1714 ImageTransportFactoryAndroid* factory =
1715 ImageTransportFactoryAndroid::GetInstance();
1716 GLHelper* gl_helper = factory->GetGLHelper();
1721 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock(
1722 new SkAutoLockPixels(*bitmap));
1723 uint8* pixels = static_cast<uint8*>(bitmap->getPixels());
1725 cc::TextureMailbox texture_mailbox;
1726 scoped_ptr<cc::SingleReleaseCallback> release_callback;
1727 result->TakeTexture(&texture_mailbox, &release_callback);
1728 DCHECK(texture_mailbox.IsTexture());
1729 if (!texture_mailbox.IsTexture())
1732 ignore_result(scoped_callback_runner.Release());
1734 gl_helper->CropScaleReadbackAndCleanMailbox(
1735 texture_mailbox.mailbox(),
1736 texture_mailbox.sync_point(),
1738 gfx::Rect(result->size()),
1742 base::Bind(&CopyFromCompositingSurfaceFinished,
1744 base::Passed(&release_callback),
1745 base::Passed(&bitmap),
1747 base::Passed(&bitmap_pixels_lock)),
1748 GLHelper::SCALER_QUALITY_GOOD);
1751 bool RenderWidgetHostViewAndroid::IsReadbackConfigSupported(
1752 SkColorType color_type) {
1753 ImageTransportFactoryAndroid* factory =
1754 ImageTransportFactoryAndroid::GetInstance();
1755 GLHelper* gl_helper = factory->GetGLHelper();
1758 return gl_helper->IsReadbackConfigSupported(color_type);
1761 SkColorType RenderWidgetHostViewAndroid::PreferredReadbackFormat() {
1762 // Define the criteria here. If say the 16 texture readback is
1763 // supported we should go with that (this degrades quality)
1764 // or stick back to the default format.
1765 if (base::SysInfo::IsLowEndDevice()) {
1766 if (IsReadbackConfigSupported(kRGB_565_SkColorType))
1767 return kRGB_565_SkColorType;
1769 return kN32_SkColorType;
1772 void RenderWidgetHostViewAndroid::ShowSelectionHandlesAutomatically() {
1773 // Fake a long press to allow automatic selection handle showing.
1774 if (selection_controller_)
1775 selection_controller_->OnLongPressEvent();
1778 void RenderWidgetHostViewAndroid::SelectRange(
1779 float x1, float y1, float x2, float y2) {
1780 if (content_view_core_)
1781 static_cast<WebContentsImpl*>(content_view_core_->GetWebContents())->
1782 SelectRange(gfx::Point(x1, y1), gfx::Point(x2, y2));
1785 void RenderWidgetHostViewAndroid::Unselect() {
1786 if (content_view_core_)
1787 content_view_core_->GetWebContents()->Unselect();
1790 void RenderWidgetHostViewAndroid::LongPress(
1791 base::TimeTicks time, float x, float y) {
1792 blink::WebGestureEvent long_press = WebGestureEventBuilder::Build(
1793 blink::WebInputEvent::GestureLongPress,
1794 (time - base::TimeTicks()).InSecondsF(), x, y);
1795 SendGestureEvent(long_press);
1799 void RenderWidgetHostViewBase::GetDefaultScreenInfo(
1800 blink::WebScreenInfo* results) {
1801 const gfx::Display& display =
1802 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
1803 results->rect = display.bounds();
1804 // TODO(husky): Remove any system controls from availableRect.
1805 results->availableRect = display.work_area();
1806 results->deviceScaleFactor = display.device_scale_factor();
1807 results->orientationAngle = display.RotationAsDegree();
1808 results->orientationType =
1809 RenderWidgetHostViewBase::GetOrientationTypeForMobile(display);
1810 gfx::DeviceDisplayInfo info;
1811 results->depth = info.GetBitsPerPixel();
1812 results->depthPerComponent = info.GetBitsPerComponent();
1813 results->isMonochrome = (results->depthPerComponent == 0);
1816 } // namespace content