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_provider_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_TextInputStateChanged
,
314 OnTextInputStateChanged
)
315 IPC_MESSAGE_HANDLER(ViewHostMsg_SmartClipDataExtracted
,
316 OnSmartClipDataExtracted
)
317 IPC_MESSAGE_UNHANDLED(handled
= false)
318 IPC_END_MESSAGE_MAP()
322 void RenderWidgetHostViewAndroid::InitAsChild(gfx::NativeView parent_view
) {
326 void RenderWidgetHostViewAndroid::InitAsPopup(
327 RenderWidgetHostView
* parent_host_view
, const gfx::Rect
& pos
) {
331 void RenderWidgetHostViewAndroid::InitAsFullscreen(
332 RenderWidgetHostView
* reference_host_view
) {
337 RenderWidgetHostViewAndroid::GetRenderWidgetHost() const {
341 void RenderWidgetHostViewAndroid::WasShown() {
342 if (!host_
|| !host_
->is_hidden())
345 host_
->WasShown(ui::LatencyInfo());
347 if (content_view_core_
) {
348 StartObservingRootWindow();
349 RequestVSyncUpdate(BEGIN_FRAME
);
353 void RenderWidgetHostViewAndroid::WasHidden() {
356 if (!host_
|| host_
->is_hidden())
359 // Inform the renderer that we are being hidden so it can reduce its resource
363 StopObservingRootWindow();
366 void RenderWidgetHostViewAndroid::WasResized() {
370 void RenderWidgetHostViewAndroid::SetSize(const gfx::Size
& size
) {
371 // Ignore the given size as only the Java code has the power to
372 // resize the view on Android.
373 default_size_
= size
;
376 void RenderWidgetHostViewAndroid::SetBounds(const gfx::Rect
& rect
) {
377 SetSize(rect
.size());
380 void RenderWidgetHostViewAndroid::AbortPendingReadbackRequests() {
381 while (!readbacks_waiting_for_frame_
.empty()) {
382 ReadbackRequest
& readback_request
= readbacks_waiting_for_frame_
.front();
383 readback_request
.GetResultCallback().Run(false, SkBitmap());
384 readbacks_waiting_for_frame_
.pop();
388 void RenderWidgetHostViewAndroid::GetScaledContentBitmap(
390 SkColorType color_type
,
391 gfx::Rect src_subrect
,
392 CopyFromCompositingSurfaceCallback
& result_callback
) {
393 if (!host_
|| host_
->is_hidden()) {
394 result_callback
.Run(false, SkBitmap());
397 if (!IsSurfaceAvailableForCopy()) {
398 // The view is visible, probably the frame has not yet arrived.
399 // Just add the ReadbackRequest to queue and wait for frame arrival
400 // to get this request processed.
401 readbacks_waiting_for_frame_
.push(
402 ReadbackRequest(scale
, color_type
, src_subrect
, result_callback
));
406 gfx::Size bounds
= layer_
->bounds();
407 if (src_subrect
.IsEmpty())
408 src_subrect
= gfx::Rect(bounds
);
409 DCHECK_LE(src_subrect
.width() + src_subrect
.x(), bounds
.width());
410 DCHECK_LE(src_subrect
.height() + src_subrect
.y(), bounds
.height());
411 const gfx::Display
& display
=
412 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
413 float device_scale_factor
= display
.device_scale_factor();
414 DCHECK_GT(device_scale_factor
, 0);
416 gfx::ToCeiledSize(gfx::ScaleSize(bounds
, scale
/ device_scale_factor
)));
417 CopyFromCompositingSurface(
418 src_subrect
, dst_size
, result_callback
, color_type
);
421 scoped_refptr
<cc::DelegatedRendererLayer
>
422 RenderWidgetHostViewAndroid::CreateDelegatedLayerForFrameProvider() const {
423 DCHECK(frame_provider_
.get());
425 scoped_refptr
<cc::DelegatedRendererLayer
> delegated_layer
=
426 cc::DelegatedRendererLayer::Create(frame_provider_
);
427 delegated_layer
->SetBounds(content_size_in_layer_
);
428 delegated_layer
->SetIsDrawable(true);
429 delegated_layer
->SetContentsOpaque(true);
431 return delegated_layer
;
434 bool RenderWidgetHostViewAndroid::HasValidFrame() const {
435 if (!content_view_core_
)
440 if (texture_size_in_layer_
.IsEmpty())
442 // This tell us whether a valid frame has arrived or not.
443 if (!frame_evictor_
->HasFrame())
449 gfx::Vector2dF
RenderWidgetHostViewAndroid::GetLastScrollOffset() const {
450 return last_scroll_offset_
;
453 gfx::NativeView
RenderWidgetHostViewAndroid::GetNativeView() const {
454 return content_view_core_
->GetViewAndroid();
457 gfx::NativeViewId
RenderWidgetHostViewAndroid::GetNativeViewId() const {
458 return reinterpret_cast<gfx::NativeViewId
>(
459 const_cast<RenderWidgetHostViewAndroid
*>(this));
462 gfx::NativeViewAccessible
463 RenderWidgetHostViewAndroid::GetNativeViewAccessible() {
468 void RenderWidgetHostViewAndroid::MovePluginWindows(
469 const std::vector
<WebPluginGeometry
>& moves
) {
470 // We don't have plugin windows on Android. Do nothing. Note: this is called
471 // from RenderWidgetHost::OnUpdateRect which is itself invoked while
472 // processing the corresponding message from Renderer.
475 void RenderWidgetHostViewAndroid::Focus() {
477 host_
->SetInputMethodActive(true);
478 if (overscroll_effect_
)
479 overscroll_effect_
->Enable();
480 if (selection_controller_
)
481 selection_controller_
->SetTemporarilyHidden(false);
484 void RenderWidgetHostViewAndroid::Blur() {
485 host_
->SetInputMethodActive(false);
487 if (overscroll_effect_
)
488 overscroll_effect_
->Disable();
489 if (selection_controller_
)
490 selection_controller_
->SetTemporarilyHidden(true);
493 bool RenderWidgetHostViewAndroid::HasFocus() const {
494 if (!content_view_core_
)
495 return false; // ContentViewCore not created yet.
497 return content_view_core_
->HasFocus();
500 bool RenderWidgetHostViewAndroid::IsSurfaceAvailableForCopy() const {
501 return HasValidFrame();
504 void RenderWidgetHostViewAndroid::Show() {
510 layer_
->SetHideLayerAndSubtree(false);
512 frame_evictor_
->SetVisible(true);
516 void RenderWidgetHostViewAndroid::Hide() {
521 if (layer_
.get() && locks_on_frame_count_
== 0)
522 layer_
->SetHideLayerAndSubtree(true);
524 frame_evictor_
->SetVisible(false);
525 // We don't know if we will ever get a frame if we are hiding the renderer, so
526 // we need to cancel all requests
527 AbortPendingReadbackRequests();
531 bool RenderWidgetHostViewAndroid::IsShowing() {
532 // ContentViewCoreImpl represents the native side of the Java
533 // ContentViewCore. It being NULL means that it is not attached
534 // to the View system yet, so we treat this RWHVA as hidden.
535 return is_showing_
&& content_view_core_
;
538 void RenderWidgetHostViewAndroid::LockCompositingSurface() {
539 DCHECK(HasValidFrame());
541 DCHECK(frame_evictor_
->HasFrame());
542 frame_evictor_
->LockFrame();
543 locks_on_frame_count_
++;
546 void RenderWidgetHostViewAndroid::UnlockCompositingSurface() {
547 if (!frame_evictor_
->HasFrame() || locks_on_frame_count_
== 0)
550 DCHECK(HasValidFrame());
551 frame_evictor_
->UnlockFrame();
552 locks_on_frame_count_
--;
554 if (locks_on_frame_count_
== 0) {
555 if (last_frame_info_
) {
556 InternalSwapCompositorFrame(last_frame_info_
->output_surface_id
,
557 last_frame_info_
->frame
.Pass());
558 last_frame_info_
.reset();
561 if (!is_showing_
&& layer_
.get())
562 layer_
->SetHideLayerAndSubtree(true);
566 void RenderWidgetHostViewAndroid::SetTextSurroundingSelectionCallback(
567 const TextSurroundingSelectionCallback
& callback
) {
568 // Only one outstanding request is allowed at any given time.
569 DCHECK(!callback
.is_null());
570 text_surrounding_selection_callback_
= callback
;
573 void RenderWidgetHostViewAndroid::OnTextSurroundingSelectionResponse(
574 const base::string16
& content
,
577 if (text_surrounding_selection_callback_
.is_null())
579 text_surrounding_selection_callback_
.Run(content
, start_offset
, end_offset
);
580 text_surrounding_selection_callback_
.Reset();
583 void RenderWidgetHostViewAndroid::ReleaseLocksOnSurface() {
584 if (!frame_evictor_
->HasFrame()) {
585 DCHECK_EQ(locks_on_frame_count_
, 0u);
588 while (locks_on_frame_count_
> 0) {
589 UnlockCompositingSurface();
594 gfx::Rect
RenderWidgetHostViewAndroid::GetViewBounds() const {
595 if (!content_view_core_
)
596 return gfx::Rect(default_size_
);
598 return gfx::Rect(content_view_core_
->GetViewSize());
601 gfx::Size
RenderWidgetHostViewAndroid::GetPhysicalBackingSize() const {
602 if (!content_view_core_
)
605 return content_view_core_
->GetPhysicalBackingSize();
608 float RenderWidgetHostViewAndroid::GetTopControlsLayoutHeight() const {
609 if (!content_view_core_
)
612 // The amount that the viewport size given to Blink is shrunk by the URL-bar.
613 return content_view_core_
->GetTopControlsLayoutHeightDip();
616 void RenderWidgetHostViewAndroid::UpdateCursor(const WebCursor
& cursor
) {
617 // There are no cursors on Android.
620 void RenderWidgetHostViewAndroid::SetIsLoading(bool is_loading
) {
621 // Do nothing. The UI notification is handled through ContentViewClient which
622 // is TabContentsDelegate.
625 void RenderWidgetHostViewAndroid::TextInputTypeChanged(
626 ui::TextInputType type
,
627 ui::TextInputMode input_mode
,
628 bool can_compose_inline
,
630 // Unused on Android, which uses OnTextInputChanged instead.
633 long RenderWidgetHostViewAndroid::GetNativeImeAdapter() {
634 return reinterpret_cast<intptr_t>(&ime_adapter_android_
);
637 void RenderWidgetHostViewAndroid::OnTextInputStateChanged(
638 const ViewHostMsg_TextInputState_Params
& params
) {
639 if (selection_controller_
) {
640 // This call is semi-redundant with that in |OnFocusedNodeChanged|. The
641 // latter is guaranteed to be called before |OnSelectionBoundsChanged|,
642 // while this call is present to ensure consistency with IME after
643 // navigation and tab focus changes
644 const bool is_editable_node
= params
.type
!= ui::TEXT_INPUT_TYPE_NONE
;
645 selection_controller_
->OnSelectionEditable(is_editable_node
);
648 // If the change is not originated from IME (e.g. Javascript, autofill),
649 // send back the renderer an acknowledgement, regardless of how we exit from
651 base::ScopedClosureRunner ack_caller
;
652 if (params
.is_non_ime_change
)
653 ack_caller
.Reset(base::Bind(&SendImeEventAck
, host_
));
658 content_view_core_
->UpdateImeAdapter(
659 GetNativeImeAdapter(),
660 static_cast<int>(params
.type
), params
.flags
,
661 params
.value
, params
.selection_start
, params
.selection_end
,
662 params
.composition_start
, params
.composition_end
,
663 params
.show_ime_if_needed
, params
.is_non_ime_change
);
666 void RenderWidgetHostViewAndroid::OnDidChangeBodyBackgroundColor(
668 if (cached_background_color_
== color
)
671 cached_background_color_
= color
;
672 if (content_view_core_
)
673 content_view_core_
->OnBackgroundColorChanged(color
);
676 void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame(bool enabled
) {
677 DCHECK(!using_synchronous_compositor_
);
678 TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame",
681 RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME
);
683 outstanding_vsync_requests_
&= ~PERSISTENT_BEGIN_FRAME
;
686 void RenderWidgetHostViewAndroid::OnStartContentIntent(
687 const GURL
& content_url
) {
688 if (content_view_core_
)
689 content_view_core_
->StartContentIntent(content_url
);
692 void RenderWidgetHostViewAndroid::OnSmartClipDataExtracted(
693 const base::string16
& text
,
694 const base::string16
& html
,
695 const gfx::Rect rect
) {
696 if (content_view_core_
)
697 content_view_core_
->OnSmartClipDataExtracted(text
, html
, rect
);
700 bool RenderWidgetHostViewAndroid::OnTouchEvent(
701 const ui::MotionEvent
& event
) {
705 if (selection_controller_
&&
706 selection_controller_
->WillHandleTouchEvent(event
))
709 if (gesture_text_selector_
.OnTouchEvent(event
))
712 if (!gesture_provider_
.OnTouchEvent(event
))
715 if (host_
->ShouldForwardTouchEvent()) {
716 blink::WebTouchEvent web_event
= CreateWebTouchEventFromMotionEvent(event
);
717 host_
->ForwardTouchEventWithLatencyInfo(web_event
,
718 CreateLatencyInfo(web_event
));
720 const bool event_consumed
= false;
721 gesture_provider_
.OnTouchEventAck(event_consumed
);
724 // Send a proactive BeginFrame on the next vsync to reduce latency.
725 // This is good enough as long as the first touch event has Begin semantics
726 // and the actual scroll happens on the next vsync.
727 if (observing_root_window_
)
728 RequestVSyncUpdate(BEGIN_FRAME
);
733 bool RenderWidgetHostViewAndroid::OnTouchHandleEvent(
734 const ui::MotionEvent
& event
) {
735 return selection_controller_
&&
736 selection_controller_
->WillHandleTouchEvent(event
);
739 void RenderWidgetHostViewAndroid::ResetGestureDetection() {
740 const ui::MotionEvent
* current_down_event
=
741 gesture_provider_
.GetCurrentDownEvent();
742 if (!current_down_event
)
745 scoped_ptr
<ui::MotionEvent
> cancel_event
= current_down_event
->Cancel();
746 DCHECK(cancel_event
);
747 OnTouchEvent(*cancel_event
);
750 void RenderWidgetHostViewAndroid::SetDoubleTapSupportEnabled(bool enabled
) {
751 gesture_provider_
.SetDoubleTapSupportForPlatformEnabled(enabled
);
754 void RenderWidgetHostViewAndroid::SetMultiTouchZoomSupportEnabled(
756 gesture_provider_
.SetMultiTouchZoomSupportEnabled(enabled
);
759 void RenderWidgetHostViewAndroid::ImeCancelComposition() {
760 ime_adapter_android_
.CancelComposition();
763 void RenderWidgetHostViewAndroid::ImeCompositionRangeChanged(
764 const gfx::Range
& range
,
765 const std::vector
<gfx::Rect
>& character_bounds
) {
766 // TODO(yukawa): Implement this.
769 void RenderWidgetHostViewAndroid::FocusedNodeChanged(bool is_editable_node
) {
770 ime_adapter_android_
.FocusedNodeChanged(is_editable_node
);
771 if (selection_controller_
)
772 selection_controller_
->OnSelectionEditable(is_editable_node
);
775 void RenderWidgetHostViewAndroid::RenderProcessGone(
776 base::TerminationStatus status
, int error_code
) {
780 void RenderWidgetHostViewAndroid::Destroy() {
782 SetContentViewCore(NULL
);
784 // The RenderWidgetHost's destruction led here, so don't call it.
790 void RenderWidgetHostViewAndroid::SetTooltipText(
791 const base::string16
& tooltip_text
) {
792 // Tooltips don't makes sense on Android.
795 void RenderWidgetHostViewAndroid::SelectionChanged(const base::string16
& text
,
797 const gfx::Range
& range
) {
798 RenderWidgetHostViewBase::SelectionChanged(text
, offset
, range
);
800 if (selection_controller_
)
801 selection_controller_
->OnSelectionEmpty(text
.empty());
803 if (!content_view_core_
)
805 if (range
.is_empty()) {
806 content_view_core_
->OnSelectionChanged("");
810 DCHECK(!text
.empty());
811 size_t pos
= range
.GetMin() - offset
;
812 size_t n
= range
.length();
814 DCHECK(pos
+ n
<= text
.length()) << "The text can not fully cover range.";
815 if (pos
>= text
.length()) {
816 NOTREACHED() << "The text can not cover range.";
820 std::string utf8_selection
= base::UTF16ToUTF8(text
.substr(pos
, n
));
822 content_view_core_
->OnSelectionChanged(utf8_selection
);
825 void RenderWidgetHostViewAndroid::SelectionBoundsChanged(
826 const ViewHostMsg_SelectionBounds_Params
& params
) {
827 NOTREACHED() << "Selection bounds should be routed through the compositor.";
830 void RenderWidgetHostViewAndroid::SetBackgroundColor(SkColor color
) {
831 RenderWidgetHostViewBase::SetBackgroundColor(color
);
832 host_
->SetBackgroundOpaque(GetBackgroundOpaque());
833 OnDidChangeBodyBackgroundColor(color
);
836 void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
837 const gfx::Rect
& src_subrect
,
838 const gfx::Size
& dst_size
,
839 CopyFromCompositingSurfaceCallback
& callback
,
840 const SkColorType color_type
) {
841 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurface");
842 if ((!host_
|| host_
->is_hidden()) ||
843 !IsReadbackConfigSupported(color_type
)) {
844 callback
.Run(false, SkBitmap());
847 base::TimeTicks start_time
= base::TimeTicks::Now();
848 if (!using_synchronous_compositor_
&& !IsSurfaceAvailableForCopy()) {
849 callback
.Run(false, SkBitmap());
852 const gfx::Display
& display
=
853 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
854 float device_scale_factor
= display
.device_scale_factor();
855 gfx::Size dst_size_in_pixel
=
856 ConvertRectToPixel(device_scale_factor
, gfx::Rect(dst_size
)).size();
857 gfx::Rect src_subrect_in_pixel
=
858 ConvertRectToPixel(device_scale_factor
, src_subrect
);
860 if (using_synchronous_compositor_
) {
861 SynchronousCopyContents(src_subrect_in_pixel
, dst_size_in_pixel
, callback
,
863 UMA_HISTOGRAM_TIMES("Compositing.CopyFromSurfaceTimeSynchronous",
864 base::TimeTicks::Now() - start_time
);
868 scoped_ptr
<cc::CopyOutputRequest
> request
;
869 scoped_refptr
<cc::Layer
> readback_layer
;
870 DCHECK(content_view_core_
);
871 DCHECK(content_view_core_
->GetWindowAndroid());
872 ui::WindowAndroidCompositor
* compositor
=
873 content_view_core_
->GetWindowAndroid()->GetCompositor();
875 DCHECK(frame_provider_
.get());
876 scoped_refptr
<cc::DelegatedRendererLayer
> delegated_layer
=
877 CreateDelegatedLayerForFrameProvider();
878 delegated_layer
->SetHideLayerAndSubtree(true);
879 compositor
->AttachLayerForReadback(delegated_layer
);
881 readback_layer
= delegated_layer
;
882 request
= cc::CopyOutputRequest::CreateRequest(
883 base::Bind(&RenderWidgetHostViewAndroid::
884 PrepareTextureCopyOutputResultForDelegatedReadback
,
890 request
->set_area(src_subrect_in_pixel
);
891 readback_layer
->RequestCopyOfOutput(request
.Pass());
894 void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame(
895 const gfx::Rect
& src_subrect
,
896 const scoped_refptr
<media::VideoFrame
>& target
,
897 const base::Callback
<void(bool)>& callback
) {
902 bool RenderWidgetHostViewAndroid::CanCopyToVideoFrame() const {
906 void RenderWidgetHostViewAndroid::ShowDisambiguationPopup(
907 const gfx::Rect
& rect_pixels
, const SkBitmap
& zoomed_bitmap
) {
908 if (!content_view_core_
)
911 content_view_core_
->ShowDisambiguationPopup(rect_pixels
, zoomed_bitmap
);
914 scoped_ptr
<SyntheticGestureTarget
>
915 RenderWidgetHostViewAndroid::CreateSyntheticGestureTarget() {
916 return scoped_ptr
<SyntheticGestureTarget
>(new SyntheticGestureTargetAndroid(
917 host_
, content_view_core_
->CreateTouchEventSynthesizer()));
920 void RenderWidgetHostViewAndroid::SendDelegatedFrameAck(
921 uint32 output_surface_id
) {
923 cc::CompositorFrameAck ack
;
924 if (resource_collection_
.get())
925 resource_collection_
->TakeUnusedResourcesForChildCompositor(&ack
.resources
);
926 RenderWidgetHostImpl::SendSwapCompositorFrameAck(host_
->GetRoutingID(),
928 host_
->GetProcess()->GetID(),
932 void RenderWidgetHostViewAndroid::SendReturnedDelegatedResources(
933 uint32 output_surface_id
) {
934 DCHECK(resource_collection_
.get());
936 cc::CompositorFrameAck ack
;
937 resource_collection_
->TakeUnusedResourcesForChildCompositor(&ack
.resources
);
938 DCHECK(!ack
.resources
.empty());
940 RenderWidgetHostImpl::SendReclaimCompositorResources(
941 host_
->GetRoutingID(),
943 host_
->GetProcess()->GetID(),
947 void RenderWidgetHostViewAndroid::UnusedResourcesAreAvailable() {
948 if (ack_callbacks_
.size())
950 SendReturnedDelegatedResources(last_output_surface_id_
);
953 void RenderWidgetHostViewAndroid::DestroyDelegatedContent() {
955 frame_provider_
= NULL
;
957 // This gets called when ever any eviction, loosing resources, swapping
958 // problems are encountered and so we abort any pending readbacks here.
959 AbortPendingReadbackRequests();
962 void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
963 uint32 output_surface_id
,
964 scoped_ptr
<cc::DelegatedFrameData
> frame_data
) {
965 bool has_content
= !texture_size_in_layer_
.IsEmpty();
967 if (output_surface_id
!= last_output_surface_id_
) {
968 // Drop the cc::DelegatedFrameResourceCollection so that we will not return
969 // any resources from the old output surface with the new output surface id.
970 if (resource_collection_
.get()) {
971 resource_collection_
->SetClient(NULL
);
972 if (resource_collection_
->LoseAllResources())
973 SendReturnedDelegatedResources(last_output_surface_id_
);
974 resource_collection_
= NULL
;
976 DestroyDelegatedContent();
978 last_output_surface_id_
= output_surface_id
;
981 // DelegatedRendererLayerImpl applies the inverse device_scale_factor of the
982 // renderer frame, assuming that the browser compositor will scale
983 // it back up to device scale. But on Android we put our browser layers in
984 // physical pixels and set our browser CC device_scale_factor to 1, so this
985 // suppresses the transform. This line may need to be removed when fixing
986 // http://crbug.com/384134 or http://crbug.com/310763
987 frame_data
->device_scale_factor
= 1.0f
;
990 DestroyDelegatedContent();
992 if (!resource_collection_
.get()) {
993 resource_collection_
= new cc::DelegatedFrameResourceCollection
;
994 resource_collection_
->SetClient(this);
996 if (!frame_provider_
.get() ||
997 texture_size_in_layer_
!= frame_provider_
->frame_size()) {
999 frame_provider_
= new cc::DelegatedFrameProvider(
1000 resource_collection_
.get(), frame_data
.Pass());
1001 layer_
= cc::DelegatedRendererLayer::Create(frame_provider_
);
1004 frame_provider_
->SetFrameData(frame_data
.Pass());
1009 layer_
->SetIsDrawable(true);
1010 layer_
->SetContentsOpaque(true);
1011 layer_
->SetBounds(content_size_in_layer_
);
1012 layer_
->SetNeedsDisplay();
1015 base::Closure ack_callback
=
1016 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck
,
1017 weak_ptr_factory_
.GetWeakPtr(),
1020 ack_callbacks_
.push(ack_callback
);
1021 if (host_
->is_hidden())
1025 void RenderWidgetHostViewAndroid::ComputeContentsSize(
1026 const cc::CompositorFrameMetadata
& frame_metadata
) {
1027 // Calculate the content size. This should be 0 if the texture_size is 0.
1028 gfx::Vector2dF offset
;
1029 if (texture_size_in_layer_
.IsEmpty())
1030 content_size_in_layer_
= gfx::Size();
1031 content_size_in_layer_
= gfx::ToCeiledSize(gfx::ScaleSize(
1032 frame_metadata
.scrollable_viewport_size
,
1033 frame_metadata
.device_scale_factor
* frame_metadata
.page_scale_factor
));
1035 if (overscroll_effect_
) {
1036 overscroll_effect_
->UpdateDisplayParameters(
1037 CreateOverscrollDisplayParameters(frame_metadata
));
1041 void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame(
1042 uint32 output_surface_id
,
1043 scoped_ptr
<cc::CompositorFrame
> frame
) {
1044 last_scroll_offset_
= frame
->metadata
.root_scroll_offset
;
1045 if (!frame
->delegated_frame_data
) {
1046 LOG(ERROR
) << "Non-delegated renderer path no longer supported";
1050 if (locks_on_frame_count_
> 0) {
1051 DCHECK(HasValidFrame());
1052 RetainFrame(output_surface_id
, frame
.Pass());
1056 if (layer_
.get() && layer_
->layer_tree_host()) {
1057 for (size_t i
= 0; i
< frame
->metadata
.latency_info
.size(); i
++) {
1058 scoped_ptr
<cc::SwapPromise
> swap_promise(
1059 new cc::LatencyInfoSwapPromise(frame
->metadata
.latency_info
[i
]));
1060 layer_
->layer_tree_host()->QueueSwapPromise(swap_promise
.Pass());
1064 DCHECK(!frame
->delegated_frame_data
->render_pass_list
.empty());
1066 cc::RenderPass
* root_pass
=
1067 frame
->delegated_frame_data
->render_pass_list
.back();
1068 texture_size_in_layer_
= root_pass
->output_rect
.size();
1069 ComputeContentsSize(frame
->metadata
);
1071 SwapDelegatedFrame(output_surface_id
, frame
->delegated_frame_data
.Pass());
1072 frame_evictor_
->SwappedFrame(!host_
->is_hidden());
1074 // As the metadata update may trigger view invalidation, always call it after
1075 // any potential compositor scheduling.
1076 OnFrameMetadataUpdated(frame
->metadata
);
1077 // Check if we have any pending readbacks, see if we have a frame available
1078 // and process them here.
1079 if (!readbacks_waiting_for_frame_
.empty()) {
1080 while (!readbacks_waiting_for_frame_
.empty()) {
1081 ReadbackRequest
& readback_request
= readbacks_waiting_for_frame_
.front();
1082 GetScaledContentBitmap(readback_request
.GetScale(),
1083 readback_request
.GetColorFormat(),
1084 readback_request
.GetCaptureRect(),
1085 readback_request
.GetResultCallback());
1086 readbacks_waiting_for_frame_
.pop();
1091 void RenderWidgetHostViewAndroid::OnSwapCompositorFrame(
1092 uint32 output_surface_id
,
1093 scoped_ptr
<cc::CompositorFrame
> frame
) {
1094 InternalSwapCompositorFrame(output_surface_id
, frame
.Pass());
1097 void RenderWidgetHostViewAndroid::RetainFrame(
1098 uint32 output_surface_id
,
1099 scoped_ptr
<cc::CompositorFrame
> frame
) {
1100 DCHECK(locks_on_frame_count_
);
1102 // Store the incoming frame so that it can be swapped when all the locks have
1103 // been released. If there is already a stored frame, then replace and skip
1104 // the previous one but make sure we still eventually send the ACK. Holding
1105 // the ACK also blocks the renderer when its max_frames_pending is reached.
1106 if (last_frame_info_
) {
1107 base::Closure ack_callback
=
1108 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck
,
1109 weak_ptr_factory_
.GetWeakPtr(),
1110 last_frame_info_
->output_surface_id
);
1112 ack_callbacks_
.push(ack_callback
);
1115 last_frame_info_
.reset(new LastFrameInfo(output_surface_id
, frame
.Pass()));
1118 void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
1119 const cc::CompositorFrameMetadata
& frame_metadata
) {
1120 // This is a subset of OnSwapCompositorFrame() used in the synchronous
1122 OnFrameMetadataUpdated(frame_metadata
);
1123 ComputeContentsSize(frame_metadata
);
1125 // DevTools ScreenCast support for Android WebView.
1126 WebContents
* web_contents
= content_view_core_
->GetWebContents();
1127 if (DevToolsAgentHost::HasFor(web_contents
)) {
1128 scoped_refptr
<DevToolsAgentHost
> dtah
=
1129 DevToolsAgentHost::GetOrCreateFor(web_contents
);
1130 // Unblock the compositor.
1131 BrowserThread::PostTask(
1132 BrowserThread::UI
, FROM_HERE
,
1133 base::Bind(&RenderViewDevToolsAgentHost::SynchronousSwapCompositorFrame
,
1134 static_cast<RenderViewDevToolsAgentHost
*>(dtah
.get()),
1139 void RenderWidgetHostViewAndroid::SetOverlayVideoMode(bool enabled
) {
1141 layer_
->SetContentsOpaque(!enabled
);
1144 bool RenderWidgetHostViewAndroid::SupportsAnimation() const {
1145 // The synchronous (WebView) compositor does not have a proper browser
1146 // compositor with which to drive animations.
1147 return !using_synchronous_compositor_
;
1150 void RenderWidgetHostViewAndroid::SetNeedsAnimate() {
1151 DCHECK(content_view_core_
);
1152 DCHECK(!using_synchronous_compositor_
);
1153 content_view_core_
->GetWindowAndroid()->SetNeedsAnimate();
1156 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::PointF
& position
) {
1157 MoveCaret(gfx::Point(position
.x(), position
.y()));
1160 void RenderWidgetHostViewAndroid::SelectBetweenCoordinates(
1161 const gfx::PointF
& start
,
1162 const gfx::PointF
& end
) {
1163 DCHECK(content_view_core_
);
1164 content_view_core_
->SelectBetweenCoordinates(start
, end
);
1167 void RenderWidgetHostViewAndroid::OnSelectionEvent(
1168 SelectionEventType event
,
1169 const gfx::PointF
& position
) {
1170 DCHECK(content_view_core_
);
1171 content_view_core_
->OnSelectionEvent(event
, position
);
1174 scoped_ptr
<TouchHandleDrawable
> RenderWidgetHostViewAndroid::CreateDrawable() {
1175 DCHECK(content_view_core_
);
1176 if (using_synchronous_compositor_
)
1177 return content_view_core_
->CreatePopupTouchHandleDrawable();
1179 return scoped_ptr
<TouchHandleDrawable
>(new CompositedTouchHandleDrawable(
1180 content_view_core_
->GetLayer().get(),
1181 content_view_core_
->GetDpiScale(),
1182 base::android::GetApplicationContext()));
1185 void RenderWidgetHostViewAndroid::SynchronousCopyContents(
1186 const gfx::Rect
& src_subrect_in_pixel
,
1187 const gfx::Size
& dst_size_in_pixel
,
1188 const base::Callback
<void(bool, const SkBitmap
&)>& callback
,
1189 const SkColorType color_type
) {
1190 SynchronousCompositor
* compositor
=
1191 SynchronousCompositorImpl::FromID(host_
->GetProcess()->GetID(),
1192 host_
->GetRoutingID());
1194 callback
.Run(false, SkBitmap());
1199 bitmap
.allocPixels(SkImageInfo::Make(dst_size_in_pixel
.width(),
1200 dst_size_in_pixel
.height(),
1202 kPremul_SkAlphaType
));
1203 SkCanvas
canvas(bitmap
);
1205 (float)dst_size_in_pixel
.width() / (float)src_subrect_in_pixel
.width(),
1206 (float)dst_size_in_pixel
.height() / (float)src_subrect_in_pixel
.height());
1207 compositor
->DemandDrawSw(&canvas
);
1208 callback
.Run(true, bitmap
);
1211 void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
1212 const cc::CompositorFrameMetadata
& frame_metadata
) {
1214 // Disable double tap zoom for pages that have a width=device-width or
1215 // narrower viewport (indicating that this is a mobile-optimized or responsive
1216 // web design, so text will be legible without zooming). Also disable
1217 // double tap and pinch for pages that prevent zooming in or out.
1218 bool has_mobile_viewport
= HasMobileViewport(frame_metadata
);
1219 bool has_fixed_page_scale
= HasFixedPageScale(frame_metadata
);
1220 gesture_provider_
.SetDoubleTapSupportForPageEnabled(
1221 !has_fixed_page_scale
&& !has_mobile_viewport
);
1223 if (!content_view_core_
)
1226 if (selection_controller_
) {
1227 selection_controller_
->OnSelectionBoundsChanged(
1228 frame_metadata
.selection_start
, frame_metadata
.selection_end
);
1231 // All offsets and sizes are in CSS pixels.
1232 content_view_core_
->UpdateFrameInfo(
1233 frame_metadata
.root_scroll_offset
,
1234 frame_metadata
.page_scale_factor
,
1235 gfx::Vector2dF(frame_metadata
.min_page_scale_factor
,
1236 frame_metadata
.max_page_scale_factor
),
1237 frame_metadata
.root_layer_size
,
1238 frame_metadata
.scrollable_viewport_size
,
1239 frame_metadata
.location_bar_offset
,
1240 frame_metadata
.location_bar_content_translation
);
1241 #if defined(VIDEO_HOLE)
1242 if (host_
&& host_
->IsRenderView()) {
1243 RenderViewHostImpl
* rvhi
= static_cast<RenderViewHostImpl
*>(
1244 RenderViewHost::From(host_
));
1245 rvhi
->media_web_contents_observer()->OnFrameInfoUpdated();
1247 #endif // defined(VIDEO_HOLE)
1250 void RenderWidgetHostViewAndroid::AcceleratedSurfaceInitialized(int route_id
) {
1251 // TODO: remove need for the surface id here
1252 accelerated_surface_route_id_
= route_id
;
1255 void RenderWidgetHostViewAndroid::AttachLayers() {
1256 if (!content_view_core_
)
1261 content_view_core_
->AttachLayer(layer_
);
1262 if (overscroll_effect_
)
1263 overscroll_effect_
->Enable();
1264 layer_
->SetHideLayerAndSubtree(!is_showing_
);
1267 void RenderWidgetHostViewAndroid::RemoveLayers() {
1268 if (!content_view_core_
)
1274 content_view_core_
->RemoveLayer(layer_
);
1275 if (overscroll_effect_
)
1276 overscroll_effect_
->Disable();
1279 void RenderWidgetHostViewAndroid::RequestVSyncUpdate(uint32 requests
) {
1280 // The synchronous compositor does not requre BeginFrame messages.
1281 if (using_synchronous_compositor_
)
1282 requests
&= FLUSH_INPUT
;
1284 bool should_request_vsync
= !outstanding_vsync_requests_
&& requests
;
1285 outstanding_vsync_requests_
|= requests
;
1286 // Note that if we're not currently observing the root window, outstanding
1287 // vsync requests will be pushed if/when we resume observing in
1288 // |StartObservingRootWindow()|.
1289 if (observing_root_window_
&& should_request_vsync
)
1290 content_view_core_
->GetWindowAndroid()->RequestVSyncUpdate();
1293 void RenderWidgetHostViewAndroid::StartObservingRootWindow() {
1294 DCHECK(content_view_core_
);
1295 if (observing_root_window_
)
1298 observing_root_window_
= true;
1299 content_view_core_
->GetWindowAndroid()->AddObserver(this);
1301 // Clear existing vsync requests to allow a request to the new window.
1302 uint32 outstanding_vsync_requests
= outstanding_vsync_requests_
;
1303 outstanding_vsync_requests_
= 0;
1304 RequestVSyncUpdate(outstanding_vsync_requests
);
1307 void RenderWidgetHostViewAndroid::StopObservingRootWindow() {
1308 if (!content_view_core_
) {
1309 DCHECK(!observing_root_window_
);
1313 if (!observing_root_window_
)
1316 observing_root_window_
= false;
1317 content_view_core_
->GetWindowAndroid()->RemoveObserver(this);
1320 void RenderWidgetHostViewAndroid::SendBeginFrame(base::TimeTicks frame_time
,
1321 base::TimeDelta vsync_period
) {
1322 TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::SendBeginFrame",
1323 "frame_time_us", frame_time
.ToInternalValue());
1324 base::TimeTicks display_time
= frame_time
+ vsync_period
;
1326 base::TimeTicks deadline
=
1327 display_time
- host_
->GetEstimatedBrowserCompositeTime();
1329 host_
->Send(new ViewMsg_BeginFrame(
1330 host_
->GetRoutingID(),
1331 cc::BeginFrameArgs::Create(frame_time
, deadline
, vsync_period
)));
1334 bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time
) {
1335 bool needs_animate
=
1336 overscroll_effect_
? overscroll_effect_
->Animate(frame_time
) : false;
1337 if (selection_controller_
)
1338 needs_animate
|= selection_controller_
->Animate(frame_time
);
1339 return needs_animate
;
1342 void RenderWidgetHostViewAndroid::EvictDelegatedFrame() {
1344 DestroyDelegatedContent();
1345 frame_evictor_
->DiscardedFrame();
1346 // We are evicting the delegated frame,
1347 // so there should be no pending readback requests
1348 DCHECK(readbacks_waiting_for_frame_
.empty());
1351 bool RenderWidgetHostViewAndroid::HasAcceleratedSurface(
1352 const gfx::Size
& desired_size
) {
1357 void RenderWidgetHostViewAndroid::GetScreenInfo(blink::WebScreenInfo
* result
) {
1358 // ScreenInfo isn't tied to the widget on Android. Always return the default.
1359 RenderWidgetHostViewBase::GetDefaultScreenInfo(result
);
1362 // TODO(jrg): Find out the implications and answer correctly here,
1363 // as we are returning the WebView and not root window bounds.
1364 gfx::Rect
RenderWidgetHostViewAndroid::GetBoundsInRootWindow() {
1365 return GetViewBounds();
1368 gfx::GLSurfaceHandle
RenderWidgetHostViewAndroid::GetCompositingSurface() {
1369 gfx::GLSurfaceHandle handle
=
1370 gfx::GLSurfaceHandle(gfx::kNullPluginWindow
, gfx::NULL_TRANSPORT
);
1371 if (CompositorImpl::IsInitialized()) {
1372 handle
.parent_client_id
=
1373 ImageTransportFactoryAndroid::GetInstance()->GetChannelID();
1378 void RenderWidgetHostViewAndroid::ProcessAckedTouchEvent(
1379 const TouchEventWithLatencyInfo
& touch
, InputEventAckState ack_result
) {
1380 const bool event_consumed
= ack_result
== INPUT_EVENT_ACK_STATE_CONSUMED
;
1381 gesture_provider_
.OnTouchEventAck(event_consumed
);
1384 void RenderWidgetHostViewAndroid::GestureEventAck(
1385 const blink::WebGestureEvent
& event
,
1386 InputEventAckState ack_result
) {
1387 // The overscroll effect requires an explicit release signal that may not be
1388 // sent from the renderer compositor.
1389 if (event
.type
== blink::WebInputEvent::GestureScrollEnd
||
1390 event
.type
== blink::WebInputEvent::GestureFlingStart
) {
1391 DidOverscroll(DidOverscrollParams());
1394 if (content_view_core_
)
1395 content_view_core_
->OnGestureEventAck(event
, ack_result
);
1398 InputEventAckState
RenderWidgetHostViewAndroid::FilterInputEvent(
1399 const blink::WebInputEvent
& input_event
) {
1400 if (selection_controller_
) {
1401 switch (input_event
.type
) {
1402 case blink::WebInputEvent::GestureLongPress
:
1403 selection_controller_
->OnLongPressEvent();
1405 case blink::WebInputEvent::GestureTap
:
1406 selection_controller_
->OnTapEvent();
1413 if (content_view_core_
&&
1414 content_view_core_
->FilterInputEvent(input_event
))
1415 return INPUT_EVENT_ACK_STATE_CONSUMED
;
1418 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED
;
1420 if (input_event
.type
== blink::WebInputEvent::GestureTapDown
||
1421 input_event
.type
== blink::WebInputEvent::TouchStart
) {
1422 GpuDataManagerImpl
* gpu_data
= GpuDataManagerImpl::GetInstance();
1423 GpuProcessHostUIShim
* shim
= GpuProcessHostUIShim::GetOneInstance();
1424 if (shim
&& gpu_data
&& accelerated_surface_route_id_
&&
1425 gpu_data
->IsDriverBugWorkaroundActive(gpu::WAKE_UP_GPU_BEFORE_DRAWING
))
1427 new AcceleratedSurfaceMsg_WakeUpGpu(accelerated_surface_route_id_
));
1430 SynchronousCompositorImpl
* compositor
=
1431 SynchronousCompositorImpl::FromID(host_
->GetProcess()->GetID(),
1432 host_
->GetRoutingID());
1434 return compositor
->HandleInputEvent(input_event
);
1435 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED
;
1438 void RenderWidgetHostViewAndroid::OnSetNeedsFlushInput() {
1439 TRACE_EVENT0("input", "RenderWidgetHostViewAndroid::OnSetNeedsFlushInput");
1440 RequestVSyncUpdate(FLUSH_INPUT
);
1443 BrowserAccessibilityManager
*
1444 RenderWidgetHostViewAndroid::CreateBrowserAccessibilityManager(
1445 BrowserAccessibilityDelegate
* delegate
) {
1446 // TODO(dmazzoni): Currently there can only be one
1447 // BrowserAccessibilityManager per ContentViewCore, so return NULL
1448 // if there's already a BrowserAccessibilityManager for the main
1449 // frame. Eventually, in order to support cross-process iframes on
1450 // Android we'll need to add support for a
1451 // BrowserAccessibilityManager for a child frame.
1452 // http://crbug.com/423846
1453 if (!host_
|| host_
->GetRootBrowserAccessibilityManager())
1456 base::android::ScopedJavaLocalRef
<jobject
> obj
;
1457 if (content_view_core_
)
1458 obj
= content_view_core_
->GetJavaObject();
1459 return new BrowserAccessibilityManagerAndroid(
1461 BrowserAccessibilityManagerAndroid::GetEmptyDocument(),
1465 bool RenderWidgetHostViewAndroid::LockMouse() {
1470 void RenderWidgetHostViewAndroid::UnlockMouse() {
1474 // Methods called from the host to the render
1476 void RenderWidgetHostViewAndroid::SendKeyEvent(
1477 const NativeWebKeyboardEvent
& event
) {
1479 host_
->ForwardKeyboardEvent(event
);
1482 void RenderWidgetHostViewAndroid::SendMouseEvent(
1483 const blink::WebMouseEvent
& event
) {
1485 host_
->ForwardMouseEvent(event
);
1488 void RenderWidgetHostViewAndroid::SendMouseWheelEvent(
1489 const blink::WebMouseWheelEvent
& event
) {
1491 host_
->ForwardWheelEvent(event
);
1494 void RenderWidgetHostViewAndroid::SendGestureEvent(
1495 const blink::WebGestureEvent
& event
) {
1496 // Sending a gesture that may trigger overscroll should resume the effect.
1497 if (overscroll_effect_
)
1498 overscroll_effect_
->Enable();
1501 host_
->ForwardGestureEventWithLatencyInfo(event
, CreateLatencyInfo(event
));
1504 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point
& point
) {
1506 host_
->MoveCaret(point
);
1509 void RenderWidgetHostViewAndroid::HideTextHandles() {
1510 if (selection_controller_
)
1511 selection_controller_
->HideAndDisallowShowingAutomatically();
1514 void RenderWidgetHostViewAndroid::OnShowingPastePopup(
1515 const gfx::PointF
& point
) {
1516 if (!selection_controller_
)
1519 // As the paste popup may be triggered *before* the bounds and editability
1520 // of the region have been updated, explicitly set the properties now.
1521 // TODO(jdduke): Remove this workaround when auxiliary paste popup
1522 // notifications are no longer required, crbug.com/398170.
1523 cc::ViewportSelectionBound insertion_bound
;
1524 insertion_bound
.type
= cc::SELECTION_BOUND_CENTER
;
1525 insertion_bound
.visible
= true;
1526 insertion_bound
.edge_top
= point
;
1527 insertion_bound
.edge_bottom
= point
;
1529 ShowSelectionHandlesAutomatically();
1530 selection_controller_
->OnSelectionEditable(true);
1531 selection_controller_
->OnSelectionEmpty(true);
1532 selection_controller_
->OnSelectionBoundsChanged(insertion_bound
,
1536 SkColor
RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const {
1537 return cached_background_color_
;
1540 void RenderWidgetHostViewAndroid::DidOverscroll(
1541 const DidOverscrollParams
& params
) {
1542 if (!content_view_core_
|| !layer_
.get() || !is_showing_
)
1545 const float device_scale_factor
= content_view_core_
->GetDpiScale();
1547 if (overscroll_effect_
&&
1548 overscroll_effect_
->OnOverscrolled(
1549 content_view_core_
->GetLayer().get(),
1550 base::TimeTicks::Now(),
1551 gfx::ScaleVector2d(params
.accumulated_overscroll
,
1552 device_scale_factor
),
1553 gfx::ScaleVector2d(params
.latest_overscroll_delta
,
1554 device_scale_factor
),
1555 gfx::ScaleVector2d(params
.current_fling_velocity
,
1556 device_scale_factor
),
1558 params
.causal_event_viewport_point
.OffsetFromOrigin(),
1559 device_scale_factor
))) {
1564 void RenderWidgetHostViewAndroid::DidStopFlinging() {
1565 if (content_view_core_
)
1566 content_view_core_
->DidStopFlinging();
1569 void RenderWidgetHostViewAndroid::SetContentViewCore(
1570 ContentViewCoreImpl
* content_view_core
) {
1572 StopObservingRootWindow();
1574 bool resize
= false;
1575 if (content_view_core
!= content_view_core_
) {
1576 overscroll_effect_
.reset();
1577 selection_controller_
.reset();
1578 ReleaseLocksOnSurface();
1582 content_view_core_
= content_view_core
;
1584 BrowserAccessibilityManager
* manager
= NULL
;
1586 manager
= host_
->GetRootBrowserAccessibilityManager();
1588 base::android::ScopedJavaLocalRef
<jobject
> obj
;
1589 if (content_view_core_
)
1590 obj
= content_view_core_
->GetJavaObject();
1591 manager
->ToBrowserAccessibilityManagerAndroid()->SetContentViewCore(obj
);
1596 if (!content_view_core_
)
1599 StartObservingRootWindow();
1604 if (!selection_controller_
)
1605 selection_controller_
= CreateSelectionController(this, content_view_core_
);
1607 if (overscroll_effect_enabled_
&& !overscroll_effect_
&&
1608 content_view_core_
->GetWindowAndroid()->GetCompositor())
1609 overscroll_effect_
= CreateOverscrollEffect(content_view_core_
);
1612 void RenderWidgetHostViewAndroid::RunAckCallbacks() {
1613 while (!ack_callbacks_
.empty()) {
1614 ack_callbacks_
.front().Run();
1615 ack_callbacks_
.pop();
1619 void RenderWidgetHostViewAndroid::OnGestureEvent(
1620 const ui::GestureEventData
& gesture
) {
1621 SendGestureEvent(CreateWebGestureEventFromGestureEventData(gesture
));
1624 void RenderWidgetHostViewAndroid::OnCompositingDidCommit() {
1628 void RenderWidgetHostViewAndroid::OnAttachCompositor() {
1629 DCHECK(content_view_core_
);
1630 if (overscroll_effect_enabled_
&& !overscroll_effect_
)
1631 overscroll_effect_
= CreateOverscrollEffect(content_view_core_
);
1634 void RenderWidgetHostViewAndroid::OnDetachCompositor() {
1635 DCHECK(content_view_core_
);
1636 DCHECK(!using_synchronous_compositor_
);
1638 overscroll_effect_
.reset();
1641 void RenderWidgetHostViewAndroid::OnVSync(base::TimeTicks frame_time
,
1642 base::TimeDelta vsync_period
) {
1643 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::OnVSync");
1647 const uint32 current_vsync_requests
= outstanding_vsync_requests_
;
1648 outstanding_vsync_requests_
= 0;
1650 if (current_vsync_requests
& FLUSH_INPUT
)
1651 host_
->FlushInput();
1653 if (current_vsync_requests
& BEGIN_FRAME
||
1654 current_vsync_requests
& PERSISTENT_BEGIN_FRAME
) {
1655 SendBeginFrame(frame_time
, vsync_period
);
1658 if (current_vsync_requests
& PERSISTENT_BEGIN_FRAME
)
1659 RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME
);
1662 void RenderWidgetHostViewAndroid::OnAnimate(base::TimeTicks begin_frame_time
) {
1663 if (Animate(begin_frame_time
))
1667 void RenderWidgetHostViewAndroid::OnLostResources() {
1668 ReleaseLocksOnSurface();
1670 DestroyDelegatedContent();
1671 DCHECK(ack_callbacks_
.empty());
1672 // We should not loose a frame if we have readback requests pending.
1673 DCHECK(readbacks_waiting_for_frame_
.empty());
1678 RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResultForDelegatedReadback(
1679 const gfx::Size
& dst_size_in_pixel
,
1680 const SkColorType color_type
,
1681 const base::TimeTicks
& start_time
,
1682 scoped_refptr
<cc::Layer
> readback_layer
,
1683 const base::Callback
<void(bool, const SkBitmap
&)>& callback
,
1684 scoped_ptr
<cc::CopyOutputResult
> result
) {
1685 readback_layer
->RemoveFromParent();
1686 PrepareTextureCopyOutputResult(
1687 dst_size_in_pixel
, color_type
, start_time
, callback
, result
.Pass());
1691 void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
1692 const gfx::Size
& dst_size_in_pixel
,
1693 const SkColorType color_type
,
1694 const base::TimeTicks
& start_time
,
1695 const base::Callback
<void(bool, const SkBitmap
&)>& callback
,
1696 scoped_ptr
<cc::CopyOutputResult
> result
) {
1697 base::ScopedClosureRunner
scoped_callback_runner(
1698 base::Bind(callback
, false, SkBitmap()));
1700 "RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult");
1702 if (!result
->HasTexture() || result
->IsEmpty() || result
->size().IsEmpty())
1705 scoped_ptr
<SkBitmap
> bitmap(new SkBitmap
);
1706 if (!bitmap
->tryAllocPixels(SkImageInfo::Make(dst_size_in_pixel
.width(),
1707 dst_size_in_pixel
.height(),
1709 kOpaque_SkAlphaType
)))
1712 ImageTransportFactoryAndroid
* factory
=
1713 ImageTransportFactoryAndroid::GetInstance();
1714 GLHelper
* gl_helper
= factory
->GetGLHelper();
1719 scoped_ptr
<SkAutoLockPixels
> bitmap_pixels_lock(
1720 new SkAutoLockPixels(*bitmap
));
1721 uint8
* pixels
= static_cast<uint8
*>(bitmap
->getPixels());
1723 cc::TextureMailbox texture_mailbox
;
1724 scoped_ptr
<cc::SingleReleaseCallback
> release_callback
;
1725 result
->TakeTexture(&texture_mailbox
, &release_callback
);
1726 DCHECK(texture_mailbox
.IsTexture());
1727 if (!texture_mailbox
.IsTexture())
1730 ignore_result(scoped_callback_runner
.Release());
1732 gl_helper
->CropScaleReadbackAndCleanMailbox(
1733 texture_mailbox
.mailbox(),
1734 texture_mailbox
.sync_point(),
1736 gfx::Rect(result
->size()),
1740 base::Bind(&CopyFromCompositingSurfaceFinished
,
1742 base::Passed(&release_callback
),
1743 base::Passed(&bitmap
),
1745 base::Passed(&bitmap_pixels_lock
)),
1746 GLHelper::SCALER_QUALITY_GOOD
);
1749 bool RenderWidgetHostViewAndroid::IsReadbackConfigSupported(
1750 SkColorType color_type
) {
1751 ImageTransportFactoryAndroid
* factory
=
1752 ImageTransportFactoryAndroid::GetInstance();
1753 GLHelper
* gl_helper
= factory
->GetGLHelper();
1756 return gl_helper
->IsReadbackConfigSupported(color_type
);
1759 SkColorType
RenderWidgetHostViewAndroid::PreferredReadbackFormat() {
1760 // Define the criteria here. If say the 16 texture readback is
1761 // supported we should go with that (this degrades quality)
1762 // or stick back to the default format.
1763 if (base::SysInfo::IsLowEndDevice()) {
1764 if (IsReadbackConfigSupported(kRGB_565_SkColorType
))
1765 return kRGB_565_SkColorType
;
1767 return kN32_SkColorType
;
1770 void RenderWidgetHostViewAndroid::ShowSelectionHandlesAutomatically() {
1771 // Fake a long press to allow automatic selection handle showing.
1772 if (selection_controller_
)
1773 selection_controller_
->OnLongPressEvent();
1776 void RenderWidgetHostViewAndroid::SelectRange(
1777 float x1
, float y1
, float x2
, float y2
) {
1778 if (content_view_core_
)
1779 static_cast<WebContentsImpl
*>(content_view_core_
->GetWebContents())->
1780 SelectRange(gfx::Point(x1
, y1
), gfx::Point(x2
, y2
));
1783 void RenderWidgetHostViewAndroid::LongPress(
1784 base::TimeTicks time
, float x
, float y
) {
1785 blink::WebGestureEvent long_press
= WebGestureEventBuilder::Build(
1786 blink::WebInputEvent::GestureLongPress
,
1787 (time
- base::TimeTicks()).InSecondsF(), x
, y
);
1788 SendGestureEvent(long_press
);
1792 void RenderWidgetHostViewBase::GetDefaultScreenInfo(
1793 blink::WebScreenInfo
* results
) {
1794 const gfx::Display
& display
=
1795 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
1796 results
->rect
= display
.bounds();
1797 // TODO(husky): Remove any system controls from availableRect.
1798 results
->availableRect
= display
.work_area();
1799 results
->deviceScaleFactor
= display
.device_scale_factor();
1800 results
->orientationAngle
= display
.RotationAsDegree();
1801 results
->orientationType
=
1802 RenderWidgetHostViewBase::GetOrientationTypeForMobile(display
);
1803 gfx::DeviceDisplayInfo info
;
1804 results
->depth
= info
.GetBitsPerPixel();
1805 results
->depthPerComponent
= info
.GetBitsPerComponent();
1806 results
->isMonochrome
= (results
->depthPerComponent
== 0);
1809 } // namespace content