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/display.h"
76 #include "ui/gfx/screen.h"
77 #include "ui/gfx/size_conversions.h"
83 const int kUndefinedOutputSurfaceId
= -1;
85 // Used to accomodate finite precision when comparing scaled viewport and
86 // content widths. While this value may seem large, width=device-width on an N7
87 // V1 saw errors of ~0.065 between computed window and content widths.
88 const float kMobileViewportWidthEpsilon
= 0.15f
;
90 // Used for conditional creation of EdgeEffect types for overscroll.
91 const int kKitKatMR2SDKVersion
= 19;
93 static const char kAsyncReadBackString
[] = "Compositing.CopyFromSurfaceTime";
95 // Sends an acknowledgement to the renderer of a processed IME event.
96 void SendImeEventAck(RenderWidgetHostImpl
* host
) {
97 host
->Send(new ViewMsg_ImeEventAck(host
->GetRoutingID()));
100 void CopyFromCompositingSurfaceFinished(
101 const base::Callback
<void(bool, const SkBitmap
&)>& callback
,
102 scoped_ptr
<cc::SingleReleaseCallback
> release_callback
,
103 scoped_ptr
<SkBitmap
> bitmap
,
104 const base::TimeTicks
& start_time
,
105 scoped_ptr
<SkAutoLockPixels
> bitmap_pixels_lock
,
108 "cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceFinished");
109 bitmap_pixels_lock
.reset();
110 release_callback
->Run(0, false);
111 UMA_HISTOGRAM_TIMES(kAsyncReadBackString
,
112 base::TimeTicks::Now() - start_time
);
113 callback
.Run(result
, *bitmap
);
116 ui::LatencyInfo
CreateLatencyInfo(const blink::WebInputEvent
& event
) {
117 ui::LatencyInfo latency_info
;
118 // The latency number should only be added if the timestamp is valid.
119 if (event
.timeStampSeconds
) {
120 const int64 time_micros
= static_cast<int64
>(
121 event
.timeStampSeconds
* base::Time::kMicrosecondsPerSecond
);
122 latency_info
.AddLatencyNumberWithTimestamp(
123 ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT
,
126 base::TimeTicks() + base::TimeDelta::FromMicroseconds(time_micros
),
132 OverscrollGlow::DisplayParameters
CreateOverscrollDisplayParameters(
133 const cc::CompositorFrameMetadata
& frame_metadata
) {
134 const float scale_factor
=
135 frame_metadata
.page_scale_factor
* frame_metadata
.device_scale_factor
;
137 // Compute the size and offsets for each edge, where each effect is sized to
138 // the viewport and offset by the distance of each viewport edge to the
139 // respective content edge.
140 OverscrollGlow::DisplayParameters params
;
141 params
.size
= gfx::ScaleSize(
142 frame_metadata
.scrollable_viewport_size
, scale_factor
);
143 params
.edge_offsets
[OverscrollGlow::EDGE_TOP
] =
144 -frame_metadata
.root_scroll_offset
.y() * scale_factor
;
145 params
.edge_offsets
[OverscrollGlow::EDGE_LEFT
] =
146 -frame_metadata
.root_scroll_offset
.x() * scale_factor
;
147 params
.edge_offsets
[OverscrollGlow::EDGE_BOTTOM
] =
148 (frame_metadata
.root_layer_size
.height() -
149 frame_metadata
.root_scroll_offset
.y() -
150 frame_metadata
.scrollable_viewport_size
.height()) *
152 params
.edge_offsets
[OverscrollGlow::EDGE_RIGHT
] =
153 (frame_metadata
.root_layer_size
.width() -
154 frame_metadata
.root_scroll_offset
.x() -
155 frame_metadata
.scrollable_viewport_size
.width()) *
161 bool UseEdgeEffectL() {
162 static bool use_edge_effect_l
=
163 base::android::BuildInfo::GetInstance()->sdk_int() > kKitKatMR2SDKVersion
;
164 return use_edge_effect_l
;
167 scoped_ptr
<EdgeEffectBase
> CreateEdgeEffect(
168 ui::SystemUIResourceManager
* resource_manager
,
169 float device_scale_factor
) {
170 DCHECK(resource_manager
);
171 if (UseEdgeEffectL())
172 return scoped_ptr
<EdgeEffectBase
>(new EdgeEffectL(resource_manager
));
174 return scoped_ptr
<EdgeEffectBase
>(
175 new EdgeEffect(resource_manager
, device_scale_factor
));
178 scoped_ptr
<OverscrollGlow
> CreateOverscrollEffect(
179 ContentViewCore
* content_view_core
) {
180 DCHECK(content_view_core
);
181 ui::WindowAndroidCompositor
* compositor
=
182 content_view_core
->GetWindowAndroid()->GetCompositor();
184 ui::SystemUIResourceManager
* system_resource_manager
=
185 &compositor
->GetSystemUIResourceManager();
187 if (UseEdgeEffectL())
188 EdgeEffectL::PreloadResources(system_resource_manager
);
190 EdgeEffect::PreloadResources(system_resource_manager
);
192 return make_scoped_ptr(
193 new OverscrollGlow(base::Bind(&CreateEdgeEffect
,
194 system_resource_manager
,
195 content_view_core
->GetDpiScale())));
198 ui::GestureProvider::Config
CreateGestureProviderConfig() {
199 ui::GestureProvider::Config config
= ui::DefaultGestureProviderConfig();
200 config
.disable_click_delay
=
201 base::CommandLine::ForCurrentProcess()->HasSwitch(
202 switches::kDisableClickDelay
);
206 bool HasFixedPageScale(const cc::CompositorFrameMetadata
& frame_metadata
) {
207 return frame_metadata
.min_page_scale_factor
==
208 frame_metadata
.max_page_scale_factor
;
211 bool HasMobileViewport(const cc::CompositorFrameMetadata
& frame_metadata
) {
212 float window_width_dip
=
213 frame_metadata
.page_scale_factor
*
214 frame_metadata
.scrollable_viewport_size
.width();
215 float content_width_css
= frame_metadata
.root_layer_size
.width();
216 return content_width_css
<= window_width_dip
+ kMobileViewportWidthEpsilon
;
219 } // anonymous namespace
221 ReadbackRequest::ReadbackRequest(
223 SkColorType color_type
,
224 gfx::Rect src_subrect
,
225 const base::Callback
<void(bool, const SkBitmap
&)>& result_callback
)
227 color_type_(color_type
),
228 src_subrect_(src_subrect
),
229 result_callback_(result_callback
) {
232 ReadbackRequest::ReadbackRequest() {
235 ReadbackRequest::~ReadbackRequest() {
238 RenderWidgetHostViewAndroid::LastFrameInfo::LastFrameInfo(
240 scoped_ptr
<cc::CompositorFrame
> output_frame
)
241 : output_surface_id(output_id
), frame(output_frame
.Pass()) {}
243 RenderWidgetHostViewAndroid::LastFrameInfo::~LastFrameInfo() {}
245 RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
246 RenderWidgetHostImpl
* widget_host
,
247 ContentViewCoreImpl
* content_view_core
)
248 : host_(widget_host
),
249 outstanding_vsync_requests_(0),
250 is_showing_(!widget_host
->is_hidden()),
251 content_view_core_(NULL
),
252 ime_adapter_android_(this),
253 cached_background_color_(SK_ColorWHITE
),
254 last_output_surface_id_(kUndefinedOutputSurfaceId
),
255 weak_ptr_factory_(this),
256 overscroll_effect_enabled_(
257 !base::CommandLine::ForCurrentProcess()->HasSwitch(
258 switches::kDisableOverscrollEdgeEffect
)),
259 gesture_provider_(CreateGestureProviderConfig(), this),
260 gesture_text_selector_(this),
261 touch_scrolling_(false),
262 potentially_active_fling_count_(0),
263 accelerated_surface_route_id_(0),
264 using_synchronous_compositor_(SynchronousCompositorImpl::FromID(
265 widget_host
->GetProcess()->GetID(),
266 widget_host
->GetRoutingID()) != NULL
),
267 frame_evictor_(new DelegatedFrameEvictor(this)),
268 locks_on_frame_count_(0),
269 observing_root_window_(false) {
270 host_
->SetView(this);
271 SetContentViewCore(content_view_core
);
272 ImageTransportFactoryAndroid::AddObserver(this);
275 RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() {
276 ImageTransportFactoryAndroid::RemoveObserver(this);
277 SetContentViewCore(NULL
);
278 DCHECK(ack_callbacks_
.empty());
279 DCHECK(readbacks_waiting_for_frame_
.empty());
280 if (resource_collection_
.get())
281 resource_collection_
->SetClient(NULL
);
285 bool RenderWidgetHostViewAndroid::OnMessageReceived(
286 const IPC::Message
& message
) {
288 IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAndroid
, message
)
289 IPC_MESSAGE_HANDLER(ViewHostMsg_StartContentIntent
, OnStartContentIntent
)
290 IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeBodyBackgroundColor
,
291 OnDidChangeBodyBackgroundColor
)
292 IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrame
,
293 OnSetNeedsBeginFrame
)
294 IPC_MESSAGE_HANDLER(ViewHostMsg_SmartClipDataExtracted
,
295 OnSmartClipDataExtracted
)
296 IPC_MESSAGE_UNHANDLED(handled
= false)
297 IPC_END_MESSAGE_MAP()
301 void RenderWidgetHostViewAndroid::InitAsChild(gfx::NativeView parent_view
) {
305 void RenderWidgetHostViewAndroid::InitAsPopup(
306 RenderWidgetHostView
* parent_host_view
, const gfx::Rect
& pos
) {
310 void RenderWidgetHostViewAndroid::InitAsFullscreen(
311 RenderWidgetHostView
* reference_host_view
) {
316 RenderWidgetHostViewAndroid::GetRenderWidgetHost() const {
320 void RenderWidgetHostViewAndroid::WasShown() {
321 if (!host_
|| !host_
->is_hidden())
324 host_
->WasShown(ui::LatencyInfo());
326 if (content_view_core_
) {
327 StartObservingRootWindow();
328 RequestVSyncUpdate(BEGIN_FRAME
);
332 void RenderWidgetHostViewAndroid::WasHidden() {
335 if (!host_
|| host_
->is_hidden())
338 // Inform the renderer that we are being hidden so it can reduce its resource
342 StopObservingRootWindow();
345 void RenderWidgetHostViewAndroid::WasResized() {
349 void RenderWidgetHostViewAndroid::SetSize(const gfx::Size
& size
) {
350 // Ignore the given size as only the Java code has the power to
351 // resize the view on Android.
352 default_size_
= size
;
355 void RenderWidgetHostViewAndroid::SetBounds(const gfx::Rect
& rect
) {
356 SetSize(rect
.size());
359 void RenderWidgetHostViewAndroid::AbortPendingReadbackRequests() {
360 while (!readbacks_waiting_for_frame_
.empty()) {
361 ReadbackRequest
& readback_request
= readbacks_waiting_for_frame_
.front();
362 readback_request
.GetResultCallback().Run(false, SkBitmap());
363 readbacks_waiting_for_frame_
.pop();
367 void RenderWidgetHostViewAndroid::GetScaledContentBitmap(
369 SkColorType color_type
,
370 gfx::Rect src_subrect
,
371 const base::Callback
<void(bool, const SkBitmap
&)>& result_callback
) {
372 if (!host_
|| host_
->is_hidden()) {
373 result_callback
.Run(false, SkBitmap());
376 if (!IsSurfaceAvailableForCopy()) {
377 // The view is visible, probably the frame has not yet arrived.
378 // Just add the ReadbackRequest to queue and wait for frame arrival
379 // to get this request processed.
380 readbacks_waiting_for_frame_
.push(
381 ReadbackRequest(scale
, color_type
, src_subrect
, result_callback
));
385 gfx::Size bounds
= layer_
->bounds();
386 if (src_subrect
.IsEmpty())
387 src_subrect
= gfx::Rect(bounds
);
388 DCHECK_LE(src_subrect
.width() + src_subrect
.x(), bounds
.width());
389 DCHECK_LE(src_subrect
.height() + src_subrect
.y(), bounds
.height());
390 const gfx::Display
& display
=
391 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
392 float device_scale_factor
= display
.device_scale_factor();
393 DCHECK_GT(device_scale_factor
, 0);
395 gfx::ToCeiledSize(gfx::ScaleSize(bounds
, scale
/ device_scale_factor
)));
396 CopyFromCompositingSurface(
397 src_subrect
, dst_size
, result_callback
, color_type
);
400 bool RenderWidgetHostViewAndroid::HasValidFrame() const {
401 if (!content_view_core_
)
406 if (texture_size_in_layer_
.IsEmpty())
408 // This tell us whether a valid frame has arrived or not.
409 if (!frame_evictor_
->HasFrame())
415 gfx::NativeView
RenderWidgetHostViewAndroid::GetNativeView() const {
416 return content_view_core_
->GetViewAndroid();
419 gfx::NativeViewId
RenderWidgetHostViewAndroid::GetNativeViewId() const {
420 return reinterpret_cast<gfx::NativeViewId
>(
421 const_cast<RenderWidgetHostViewAndroid
*>(this));
424 gfx::NativeViewAccessible
425 RenderWidgetHostViewAndroid::GetNativeViewAccessible() {
430 void RenderWidgetHostViewAndroid::MovePluginWindows(
431 const std::vector
<WebPluginGeometry
>& moves
) {
432 // We don't have plugin windows on Android. Do nothing. Note: this is called
433 // from RenderWidgetHost::OnUpdateRect which is itself invoked while
434 // processing the corresponding message from Renderer.
437 void RenderWidgetHostViewAndroid::Focus() {
439 host_
->SetInputMethodActive(true);
440 if (overscroll_effect_
)
441 overscroll_effect_
->Enable();
444 void RenderWidgetHostViewAndroid::Blur() {
445 host_
->ExecuteEditCommand("Unselect", "");
446 host_
->SetInputMethodActive(false);
448 if (overscroll_effect_
)
449 overscroll_effect_
->Disable();
452 bool RenderWidgetHostViewAndroid::HasFocus() const {
453 if (!content_view_core_
)
454 return false; // ContentViewCore not created yet.
456 return content_view_core_
->HasFocus();
459 bool RenderWidgetHostViewAndroid::IsSurfaceAvailableForCopy() const {
460 return HasValidFrame();
463 void RenderWidgetHostViewAndroid::Show() {
469 layer_
->SetHideLayerAndSubtree(false);
471 frame_evictor_
->SetVisible(true);
475 void RenderWidgetHostViewAndroid::Hide() {
480 if (layer_
&& locks_on_frame_count_
== 0)
481 layer_
->SetHideLayerAndSubtree(true);
483 frame_evictor_
->SetVisible(false);
484 // We don't know if we will ever get a frame if we are hiding the renderer, so
485 // we need to cancel all requests
486 AbortPendingReadbackRequests();
490 bool RenderWidgetHostViewAndroid::IsShowing() {
491 // ContentViewCoreImpl represents the native side of the Java
492 // ContentViewCore. It being NULL means that it is not attached
493 // to the View system yet, so we treat this RWHVA as hidden.
494 return is_showing_
&& content_view_core_
;
497 void RenderWidgetHostViewAndroid::LockCompositingSurface() {
498 DCHECK(HasValidFrame());
500 DCHECK(frame_evictor_
->HasFrame());
501 frame_evictor_
->LockFrame();
502 locks_on_frame_count_
++;
505 void RenderWidgetHostViewAndroid::UnlockCompositingSurface() {
506 if (!frame_evictor_
->HasFrame() || locks_on_frame_count_
== 0)
509 DCHECK(HasValidFrame());
510 frame_evictor_
->UnlockFrame();
511 locks_on_frame_count_
--;
513 if (locks_on_frame_count_
== 0) {
514 if (last_frame_info_
) {
515 InternalSwapCompositorFrame(last_frame_info_
->output_surface_id
,
516 last_frame_info_
->frame
.Pass());
517 last_frame_info_
.reset();
520 if (!is_showing_
&& layer_
)
521 layer_
->SetHideLayerAndSubtree(true);
525 void RenderWidgetHostViewAndroid::SetTextSurroundingSelectionCallback(
526 const TextSurroundingSelectionCallback
& callback
) {
527 // Only one outstanding request is allowed at any given time.
528 DCHECK(!callback
.is_null());
529 text_surrounding_selection_callback_
= callback
;
532 void RenderWidgetHostViewAndroid::OnTextSurroundingSelectionResponse(
533 const base::string16
& content
,
536 if (text_surrounding_selection_callback_
.is_null())
538 text_surrounding_selection_callback_
.Run(content
, start_offset
, end_offset
);
539 text_surrounding_selection_callback_
.Reset();
542 void RenderWidgetHostViewAndroid::ReleaseLocksOnSurface() {
543 if (!frame_evictor_
->HasFrame()) {
544 DCHECK_EQ(locks_on_frame_count_
, 0u);
547 while (locks_on_frame_count_
> 0) {
548 UnlockCompositingSurface();
553 gfx::Rect
RenderWidgetHostViewAndroid::GetViewBounds() const {
554 if (!content_view_core_
)
555 return gfx::Rect(default_size_
);
557 return gfx::Rect(content_view_core_
->GetViewSize());
560 gfx::Size
RenderWidgetHostViewAndroid::GetPhysicalBackingSize() const {
561 if (!content_view_core_
)
564 return content_view_core_
->GetPhysicalBackingSize();
567 float RenderWidgetHostViewAndroid::GetTopControlsLayoutHeight() const {
568 if (!content_view_core_
)
571 // The amount that the viewport size given to Blink is shrunk by the URL-bar.
572 return content_view_core_
->GetTopControlsLayoutHeightDip();
575 void RenderWidgetHostViewAndroid::UpdateCursor(const WebCursor
& cursor
) {
576 // There are no cursors on Android.
579 void RenderWidgetHostViewAndroid::SetIsLoading(bool is_loading
) {
580 // Do nothing. The UI notification is handled through ContentViewClient which
581 // is TabContentsDelegate.
584 long RenderWidgetHostViewAndroid::GetNativeImeAdapter() {
585 return reinterpret_cast<intptr_t>(&ime_adapter_android_
);
588 void RenderWidgetHostViewAndroid::TextInputStateChanged(
589 const ViewHostMsg_TextInputState_Params
& params
) {
590 if (selection_controller_
) {
591 // This call is semi-redundant with that in |OnFocusedNodeChanged|. The
592 // latter is guaranteed to be called before |OnSelectionBoundsChanged|,
593 // while this call is present to ensure consistency with IME after
594 // navigation and tab focus changes
595 const bool is_editable_node
= params
.type
!= ui::TEXT_INPUT_TYPE_NONE
;
596 selection_controller_
->OnSelectionEditable(is_editable_node
);
599 // If the change is not originated from IME (e.g. Javascript, autofill),
600 // send back the renderer an acknowledgement, regardless of how we exit from
602 base::ScopedClosureRunner ack_caller
;
603 if (params
.is_non_ime_change
)
604 ack_caller
.Reset(base::Bind(&SendImeEventAck
, host_
));
609 content_view_core_
->UpdateImeAdapter(
610 GetNativeImeAdapter(),
611 static_cast<int>(params
.type
), params
.flags
,
612 params
.value
, params
.selection_start
, params
.selection_end
,
613 params
.composition_start
, params
.composition_end
,
614 params
.show_ime_if_needed
, params
.is_non_ime_change
);
617 void RenderWidgetHostViewAndroid::OnDidChangeBodyBackgroundColor(
619 if (cached_background_color_
== color
)
622 cached_background_color_
= color
;
623 if (content_view_core_
)
624 content_view_core_
->OnBackgroundColorChanged(color
);
627 void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame(bool enabled
) {
628 DCHECK(!using_synchronous_compositor_
);
629 TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame",
632 RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME
);
634 outstanding_vsync_requests_
&= ~PERSISTENT_BEGIN_FRAME
;
637 void RenderWidgetHostViewAndroid::OnStartContentIntent(
638 const GURL
& content_url
) {
639 if (content_view_core_
)
640 content_view_core_
->StartContentIntent(content_url
);
643 void RenderWidgetHostViewAndroid::OnSmartClipDataExtracted(
644 const base::string16
& text
,
645 const base::string16
& html
,
646 const gfx::Rect rect
) {
647 if (content_view_core_
)
648 content_view_core_
->OnSmartClipDataExtracted(text
, html
, rect
);
651 bool RenderWidgetHostViewAndroid::OnTouchEvent(
652 const ui::MotionEvent
& event
) {
656 if (selection_controller_
&&
657 selection_controller_
->WillHandleTouchEvent(event
))
660 if (!gesture_provider_
.OnTouchEvent(event
))
663 if (gesture_text_selector_
.OnTouchEvent(event
)) {
664 gesture_provider_
.OnTouchEventAck(false);
668 // Short-circuit touch forwarding if no touch handlers exist.
669 if (!host_
->ShouldForwardTouchEvent()) {
670 const bool event_consumed
= false;
671 gesture_provider_
.OnTouchEventAck(event_consumed
);
675 SendTouchEvent(CreateWebTouchEventFromMotionEvent(event
));
679 bool RenderWidgetHostViewAndroid::OnTouchHandleEvent(
680 const ui::MotionEvent
& event
) {
681 return selection_controller_
&&
682 selection_controller_
->WillHandleTouchEvent(event
);
685 void RenderWidgetHostViewAndroid::ResetGestureDetection() {
686 const ui::MotionEvent
* current_down_event
=
687 gesture_provider_
.GetCurrentDownEvent();
688 if (!current_down_event
)
691 scoped_ptr
<ui::MotionEvent
> cancel_event
= current_down_event
->Cancel();
692 DCHECK(cancel_event
);
693 OnTouchEvent(*cancel_event
);
695 touch_scrolling_
= false;
696 potentially_active_fling_count_
= 0;
697 OnContentScrollingChange();
700 void RenderWidgetHostViewAndroid::SetDoubleTapSupportEnabled(bool enabled
) {
701 gesture_provider_
.SetDoubleTapSupportForPlatformEnabled(enabled
);
704 void RenderWidgetHostViewAndroid::SetMultiTouchZoomSupportEnabled(
706 gesture_provider_
.SetMultiTouchZoomSupportEnabled(enabled
);
709 void RenderWidgetHostViewAndroid::ImeCancelComposition() {
710 ime_adapter_android_
.CancelComposition();
713 void RenderWidgetHostViewAndroid::FocusedNodeChanged(bool is_editable_node
) {
714 ime_adapter_android_
.FocusedNodeChanged(is_editable_node
);
715 if (selection_controller_
)
716 selection_controller_
->OnSelectionEditable(is_editable_node
);
719 void RenderWidgetHostViewAndroid::RenderProcessGone(
720 base::TerminationStatus status
, int error_code
) {
724 void RenderWidgetHostViewAndroid::Destroy() {
726 SetContentViewCore(NULL
);
728 // The RenderWidgetHost's destruction led here, so don't call it.
734 void RenderWidgetHostViewAndroid::SetTooltipText(
735 const base::string16
& tooltip_text
) {
736 // Tooltips don't makes sense on Android.
739 void RenderWidgetHostViewAndroid::SelectionChanged(const base::string16
& text
,
741 const gfx::Range
& range
) {
742 RenderWidgetHostViewBase::SelectionChanged(text
, offset
, range
);
744 if (selection_controller_
)
745 selection_controller_
->OnSelectionEmpty(text
.empty());
747 if (!content_view_core_
)
749 if (range
.is_empty()) {
750 content_view_core_
->OnSelectionChanged("");
754 DCHECK(!text
.empty());
755 size_t pos
= range
.GetMin() - offset
;
756 size_t n
= range
.length();
758 DCHECK(pos
+ n
<= text
.length()) << "The text can not fully cover range.";
759 if (pos
>= text
.length()) {
760 NOTREACHED() << "The text can not cover range.";
764 std::string utf8_selection
= base::UTF16ToUTF8(text
.substr(pos
, n
));
766 content_view_core_
->OnSelectionChanged(utf8_selection
);
769 void RenderWidgetHostViewAndroid::SelectionBoundsChanged(
770 const ViewHostMsg_SelectionBounds_Params
& params
) {
771 if (!selection_controller_
)
774 gfx::RectF
start_rect(params
.anchor_rect
);
775 gfx::RectF
end_rect(params
.focus_rect
);
776 if (params
.is_anchor_first
)
777 std::swap(start_rect
, end_rect
);
779 cc::ViewportSelectionBound start_bound
, end_bound
;
780 start_bound
.visible
= true;
781 end_bound
.visible
= true;
782 start_bound
.edge_top
= start_rect
.origin();
783 start_bound
.edge_bottom
= start_rect
.bottom_left();
784 end_bound
.edge_top
= end_rect
.origin();
785 end_bound
.edge_bottom
= end_rect
.bottom_left();
787 if (params
.anchor_rect
== params
.focus_rect
) {
788 if (params
.anchor_rect
.x() && params
.anchor_rect
.y())
789 start_bound
.type
= end_bound
.type
= cc::SELECTION_BOUND_CENTER
;
791 start_bound
.type
= params
.anchor_dir
== blink::WebTextDirectionRightToLeft
792 ? cc::SELECTION_BOUND_LEFT
793 : cc::SELECTION_BOUND_RIGHT
;
794 end_bound
.type
= params
.focus_dir
== blink::WebTextDirectionRightToLeft
795 ? cc::SELECTION_BOUND_RIGHT
796 : cc::SELECTION_BOUND_LEFT
;
799 selection_controller_
->OnSelectionBoundsChanged(start_bound
, end_bound
);
802 void RenderWidgetHostViewAndroid::SetBackgroundOpaque(bool opaque
) {
803 RenderWidgetHostViewBase::SetBackgroundOpaque(opaque
);
804 host_
->SetBackgroundOpaque(opaque
);
807 void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
808 const gfx::Rect
& src_subrect
,
809 const gfx::Size
& dst_size
,
810 const base::Callback
<void(bool, const SkBitmap
&)>& callback
,
811 const SkColorType color_type
) {
812 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurface");
813 if ((!host_
|| host_
->is_hidden()) ||
814 !IsReadbackConfigSupported(color_type
)) {
815 callback
.Run(false, SkBitmap());
818 base::TimeTicks start_time
= base::TimeTicks::Now();
819 if (!using_synchronous_compositor_
&& !IsSurfaceAvailableForCopy()) {
820 callback
.Run(false, SkBitmap());
823 const gfx::Display
& display
=
824 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
825 float device_scale_factor
= display
.device_scale_factor();
826 gfx::Size dst_size_in_pixel
=
827 ConvertRectToPixel(device_scale_factor
, gfx::Rect(dst_size
)).size();
828 gfx::Rect src_subrect_in_pixel
=
829 ConvertRectToPixel(device_scale_factor
, src_subrect
);
831 if (using_synchronous_compositor_
) {
832 SynchronousCopyContents(src_subrect_in_pixel
, dst_size_in_pixel
, callback
,
834 UMA_HISTOGRAM_TIMES("Compositing.CopyFromSurfaceTimeSynchronous",
835 base::TimeTicks::Now() - start_time
);
839 scoped_ptr
<cc::CopyOutputRequest
> request
;
840 scoped_refptr
<cc::Layer
> readback_layer
;
841 DCHECK(content_view_core_
);
842 DCHECK(content_view_core_
->GetWindowAndroid());
843 ui::WindowAndroidCompositor
* compositor
=
844 content_view_core_
->GetWindowAndroid()->GetCompositor();
846 DCHECK(frame_provider_
);
847 scoped_refptr
<cc::DelegatedRendererLayer
> delegated_layer
=
848 cc::DelegatedRendererLayer::Create(frame_provider_
);
849 delegated_layer
->SetBounds(content_size_in_layer_
);
850 delegated_layer
->SetHideLayerAndSubtree(true);
851 delegated_layer
->SetIsDrawable(true);
852 delegated_layer
->SetContentsOpaque(true);
853 compositor
->AttachLayerForReadback(delegated_layer
);
855 readback_layer
= delegated_layer
;
856 request
= cc::CopyOutputRequest::CreateRequest(
857 base::Bind(&RenderWidgetHostViewAndroid::
858 PrepareTextureCopyOutputResultForDelegatedReadback
,
864 request
->set_area(src_subrect_in_pixel
);
865 readback_layer
->RequestCopyOfOutput(request
.Pass());
868 void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame(
869 const gfx::Rect
& src_subrect
,
870 const scoped_refptr
<media::VideoFrame
>& target
,
871 const base::Callback
<void(bool)>& callback
) {
876 bool RenderWidgetHostViewAndroid::CanCopyToVideoFrame() const {
880 void RenderWidgetHostViewAndroid::ShowDisambiguationPopup(
881 const gfx::Rect
& target_rect
, const SkBitmap
& zoomed_bitmap
) {
882 if (!content_view_core_
)
885 content_view_core_
->ShowDisambiguationPopup(target_rect
, zoomed_bitmap
);
888 scoped_ptr
<SyntheticGestureTarget
>
889 RenderWidgetHostViewAndroid::CreateSyntheticGestureTarget() {
890 return scoped_ptr
<SyntheticGestureTarget
>(new SyntheticGestureTargetAndroid(
891 host_
, content_view_core_
->CreateTouchEventSynthesizer()));
894 void RenderWidgetHostViewAndroid::SendDelegatedFrameAck(
895 uint32 output_surface_id
) {
897 cc::CompositorFrameAck ack
;
898 if (resource_collection_
.get())
899 resource_collection_
->TakeUnusedResourcesForChildCompositor(&ack
.resources
);
900 RenderWidgetHostImpl::SendSwapCompositorFrameAck(host_
->GetRoutingID(),
902 host_
->GetProcess()->GetID(),
906 void RenderWidgetHostViewAndroid::SendReturnedDelegatedResources(
907 uint32 output_surface_id
) {
908 DCHECK(resource_collection_
);
910 cc::CompositorFrameAck ack
;
911 resource_collection_
->TakeUnusedResourcesForChildCompositor(&ack
.resources
);
912 DCHECK(!ack
.resources
.empty());
914 RenderWidgetHostImpl::SendReclaimCompositorResources(
915 host_
->GetRoutingID(),
917 host_
->GetProcess()->GetID(),
921 void RenderWidgetHostViewAndroid::UnusedResourcesAreAvailable() {
922 if (ack_callbacks_
.size())
924 SendReturnedDelegatedResources(last_output_surface_id_
);
927 void RenderWidgetHostViewAndroid::DestroyDelegatedContent() {
929 frame_provider_
= NULL
;
931 // This gets called when ever any eviction, loosing resources, swapping
932 // problems are encountered and so we abort any pending readbacks here.
933 AbortPendingReadbackRequests();
936 void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
937 uint32 output_surface_id
,
938 scoped_ptr
<cc::DelegatedFrameData
> frame_data
) {
939 bool has_content
= !texture_size_in_layer_
.IsEmpty();
941 if (output_surface_id
!= last_output_surface_id_
) {
942 // Drop the cc::DelegatedFrameResourceCollection so that we will not return
943 // any resources from the old output surface with the new output surface id.
944 if (resource_collection_
.get()) {
945 resource_collection_
->SetClient(NULL
);
946 if (resource_collection_
->LoseAllResources())
947 SendReturnedDelegatedResources(last_output_surface_id_
);
948 resource_collection_
= NULL
;
950 DestroyDelegatedContent();
952 last_output_surface_id_
= output_surface_id
;
955 // DelegatedRendererLayerImpl applies the inverse device_scale_factor of the
956 // renderer frame, assuming that the browser compositor will scale
957 // it back up to device scale. But on Android we put our browser layers in
958 // physical pixels and set our browser CC device_scale_factor to 1, so this
959 // suppresses the transform. This line may need to be removed when fixing
960 // http://crbug.com/384134 or http://crbug.com/310763
961 frame_data
->device_scale_factor
= 1.0f
;
964 DestroyDelegatedContent();
966 if (!resource_collection_
.get()) {
967 resource_collection_
= new cc::DelegatedFrameResourceCollection
;
968 resource_collection_
->SetClient(this);
970 if (!frame_provider_
||
971 texture_size_in_layer_
!= frame_provider_
->frame_size()) {
973 frame_provider_
= new cc::DelegatedFrameProvider(
974 resource_collection_
.get(), frame_data
.Pass());
975 layer_
= cc::DelegatedRendererLayer::Create(frame_provider_
);
978 frame_provider_
->SetFrameData(frame_data
.Pass());
983 layer_
->SetIsDrawable(true);
984 layer_
->SetContentsOpaque(true);
985 layer_
->SetBounds(content_size_in_layer_
);
986 layer_
->SetNeedsDisplay();
989 base::Closure ack_callback
=
990 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck
,
991 weak_ptr_factory_
.GetWeakPtr(),
994 ack_callbacks_
.push(ack_callback
);
995 if (host_
->is_hidden())
999 void RenderWidgetHostViewAndroid::ComputeContentsSize(
1000 const cc::CompositorFrameMetadata
& frame_metadata
) {
1001 // Calculate the content size. This should be 0 if the texture_size is 0.
1002 gfx::Vector2dF offset
;
1003 if (texture_size_in_layer_
.IsEmpty())
1004 content_size_in_layer_
= gfx::Size();
1005 content_size_in_layer_
= gfx::ToCeiledSize(gfx::ScaleSize(
1006 frame_metadata
.scrollable_viewport_size
,
1007 frame_metadata
.device_scale_factor
* frame_metadata
.page_scale_factor
));
1009 if (overscroll_effect_
) {
1010 overscroll_effect_
->UpdateDisplayParameters(
1011 CreateOverscrollDisplayParameters(frame_metadata
));
1015 void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame(
1016 uint32 output_surface_id
,
1017 scoped_ptr
<cc::CompositorFrame
> frame
) {
1018 if (!frame
->delegated_frame_data
) {
1019 LOG(ERROR
) << "Non-delegated renderer path no longer supported";
1023 if (locks_on_frame_count_
> 0) {
1024 DCHECK(HasValidFrame());
1025 RetainFrame(output_surface_id
, frame
.Pass());
1029 if (layer_
&& layer_
->layer_tree_host()) {
1030 for (size_t i
= 0; i
< frame
->metadata
.latency_info
.size(); i
++) {
1031 scoped_ptr
<cc::SwapPromise
> swap_promise(
1032 new cc::LatencyInfoSwapPromise(frame
->metadata
.latency_info
[i
]));
1033 layer_
->layer_tree_host()->QueueSwapPromise(swap_promise
.Pass());
1037 DCHECK(!frame
->delegated_frame_data
->render_pass_list
.empty());
1039 cc::RenderPass
* root_pass
=
1040 frame
->delegated_frame_data
->render_pass_list
.back();
1041 texture_size_in_layer_
= root_pass
->output_rect
.size();
1042 ComputeContentsSize(frame
->metadata
);
1044 SwapDelegatedFrame(output_surface_id
, frame
->delegated_frame_data
.Pass());
1045 frame_evictor_
->SwappedFrame(!host_
->is_hidden());
1047 // As the metadata update may trigger view invalidation, always call it after
1048 // any potential compositor scheduling.
1049 OnFrameMetadataUpdated(frame
->metadata
);
1050 // Check if we have any pending readbacks, see if we have a frame available
1051 // and process them here.
1052 if (!readbacks_waiting_for_frame_
.empty()) {
1053 while (!readbacks_waiting_for_frame_
.empty()) {
1054 ReadbackRequest
& readback_request
= readbacks_waiting_for_frame_
.front();
1055 GetScaledContentBitmap(readback_request
.GetScale(),
1056 readback_request
.GetColorFormat(),
1057 readback_request
.GetCaptureRect(),
1058 readback_request
.GetResultCallback());
1059 readbacks_waiting_for_frame_
.pop();
1064 void RenderWidgetHostViewAndroid::OnSwapCompositorFrame(
1065 uint32 output_surface_id
,
1066 scoped_ptr
<cc::CompositorFrame
> frame
) {
1067 InternalSwapCompositorFrame(output_surface_id
, frame
.Pass());
1070 void RenderWidgetHostViewAndroid::RetainFrame(
1071 uint32 output_surface_id
,
1072 scoped_ptr
<cc::CompositorFrame
> frame
) {
1073 DCHECK(locks_on_frame_count_
);
1075 // Store the incoming frame so that it can be swapped when all the locks have
1076 // been released. If there is already a stored frame, then replace and skip
1077 // the previous one but make sure we still eventually send the ACK. Holding
1078 // the ACK also blocks the renderer when its max_frames_pending is reached.
1079 if (last_frame_info_
) {
1080 base::Closure ack_callback
=
1081 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck
,
1082 weak_ptr_factory_
.GetWeakPtr(),
1083 last_frame_info_
->output_surface_id
);
1085 ack_callbacks_
.push(ack_callback
);
1088 last_frame_info_
.reset(new LastFrameInfo(output_surface_id
, frame
.Pass()));
1091 void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
1092 const cc::CompositorFrameMetadata
& frame_metadata
) {
1093 // This is a subset of OnSwapCompositorFrame() used in the synchronous
1095 OnFrameMetadataUpdated(frame_metadata
);
1096 ComputeContentsSize(frame_metadata
);
1098 // DevTools ScreenCast support for Android WebView.
1099 WebContents
* web_contents
= content_view_core_
->GetWebContents();
1100 if (DevToolsAgentHost::HasFor(web_contents
)) {
1101 scoped_refptr
<DevToolsAgentHost
> dtah
=
1102 DevToolsAgentHost::GetOrCreateFor(web_contents
);
1103 // Unblock the compositor.
1104 BrowserThread::PostTask(
1105 BrowserThread::UI
, FROM_HERE
,
1106 base::Bind(&RenderViewDevToolsAgentHost::SynchronousSwapCompositorFrame
,
1107 static_cast<RenderViewDevToolsAgentHost
*>(dtah
.get()),
1112 void RenderWidgetHostViewAndroid::SetOverlayVideoMode(bool enabled
) {
1114 layer_
->SetContentsOpaque(!enabled
);
1117 bool RenderWidgetHostViewAndroid::SupportsAnimation() const {
1118 // The synchronous (WebView) compositor does not have a proper browser
1119 // compositor with which to drive animations.
1120 return !using_synchronous_compositor_
;
1123 void RenderWidgetHostViewAndroid::SetNeedsAnimate() {
1124 DCHECK(content_view_core_
);
1125 DCHECK(!using_synchronous_compositor_
);
1126 content_view_core_
->GetWindowAndroid()->SetNeedsAnimate();
1129 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::PointF
& position
) {
1130 MoveCaret(gfx::Point(position
.x(), position
.y()));
1133 void RenderWidgetHostViewAndroid::SelectBetweenCoordinates(
1134 const gfx::PointF
& start
,
1135 const gfx::PointF
& end
) {
1136 DCHECK(content_view_core_
);
1137 content_view_core_
->SelectBetweenCoordinates(start
, end
);
1140 void RenderWidgetHostViewAndroid::OnSelectionEvent(
1141 SelectionEventType event
,
1142 const gfx::PointF
& position
) {
1143 DCHECK(content_view_core_
);
1144 content_view_core_
->OnSelectionEvent(event
, position
);
1147 scoped_ptr
<TouchHandleDrawable
> RenderWidgetHostViewAndroid::CreateDrawable() {
1148 DCHECK(content_view_core_
);
1149 if (using_synchronous_compositor_
)
1150 return content_view_core_
->CreatePopupTouchHandleDrawable();
1152 return scoped_ptr
<TouchHandleDrawable
>(new CompositedTouchHandleDrawable(
1153 content_view_core_
->GetLayer(),
1154 content_view_core_
->GetDpiScale(),
1155 base::android::GetApplicationContext()));
1158 void RenderWidgetHostViewAndroid::SynchronousCopyContents(
1159 const gfx::Rect
& src_subrect_in_pixel
,
1160 const gfx::Size
& dst_size_in_pixel
,
1161 const base::Callback
<void(bool, const SkBitmap
&)>& callback
,
1162 const SkColorType color_type
) {
1163 SynchronousCompositor
* compositor
=
1164 SynchronousCompositorImpl::FromID(host_
->GetProcess()->GetID(),
1165 host_
->GetRoutingID());
1167 callback
.Run(false, SkBitmap());
1172 bitmap
.allocPixels(SkImageInfo::Make(dst_size_in_pixel
.width(),
1173 dst_size_in_pixel
.height(),
1175 kPremul_SkAlphaType
));
1176 SkCanvas
canvas(bitmap
);
1178 (float)dst_size_in_pixel
.width() / (float)src_subrect_in_pixel
.width(),
1179 (float)dst_size_in_pixel
.height() / (float)src_subrect_in_pixel
.height());
1180 compositor
->DemandDrawSw(&canvas
);
1181 callback
.Run(true, bitmap
);
1184 void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
1185 const cc::CompositorFrameMetadata
& frame_metadata
) {
1187 // Disable double tap zoom for pages that have a width=device-width or
1188 // narrower viewport (indicating that this is a mobile-optimized or responsive
1189 // web design, so text will be legible without zooming). Also disable
1190 // double tap and pinch for pages that prevent zooming in or out.
1191 bool has_mobile_viewport
= HasMobileViewport(frame_metadata
);
1192 bool has_fixed_page_scale
= HasFixedPageScale(frame_metadata
);
1193 gesture_provider_
.SetDoubleTapSupportForPageEnabled(
1194 !has_fixed_page_scale
&& !has_mobile_viewport
);
1196 if (!content_view_core_
)
1199 // All offsets and sizes are in CSS pixels.
1200 content_view_core_
->UpdateFrameInfo(
1201 frame_metadata
.root_scroll_offset
,
1202 frame_metadata
.page_scale_factor
,
1203 gfx::Vector2dF(frame_metadata
.min_page_scale_factor
,
1204 frame_metadata
.max_page_scale_factor
),
1205 frame_metadata
.root_layer_size
,
1206 frame_metadata
.scrollable_viewport_size
,
1207 frame_metadata
.location_bar_offset
,
1208 frame_metadata
.location_bar_content_translation
);
1209 #if defined(VIDEO_HOLE)
1210 if (host_
&& host_
->IsRenderView()) {
1211 RenderViewHostImpl
* rvhi
= static_cast<RenderViewHostImpl
*>(
1212 RenderViewHost::From(host_
));
1213 rvhi
->media_web_contents_observer()->OnFrameInfoUpdated();
1215 #endif // defined(VIDEO_HOLE)
1218 void RenderWidgetHostViewAndroid::AcceleratedSurfaceInitialized(int host_id
,
1220 accelerated_surface_route_id_
= route_id
;
1223 void RenderWidgetHostViewAndroid::AcceleratedSurfaceBuffersSwapped(
1224 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params
& params
,
1226 NOTREACHED() << "Need --composite-to-mailbox or --enable-delegated-renderer";
1229 void RenderWidgetHostViewAndroid::AttachLayers() {
1230 if (!content_view_core_
)
1235 content_view_core_
->AttachLayer(layer_
);
1236 if (overscroll_effect_
)
1237 overscroll_effect_
->Enable();
1238 layer_
->SetHideLayerAndSubtree(!is_showing_
);
1241 void RenderWidgetHostViewAndroid::RemoveLayers() {
1242 if (!content_view_core_
)
1248 content_view_core_
->RemoveLayer(layer_
);
1249 if (overscroll_effect_
)
1250 overscroll_effect_
->Disable();
1253 void RenderWidgetHostViewAndroid::RequestVSyncUpdate(uint32 requests
) {
1254 // The synchronous compositor does not requre BeginFrame messages.
1255 if (using_synchronous_compositor_
)
1256 requests
&= FLUSH_INPUT
;
1258 bool should_request_vsync
= !outstanding_vsync_requests_
&& requests
;
1259 outstanding_vsync_requests_
|= requests
;
1260 // Note that if we're not currently observing the root window, outstanding
1261 // vsync requests will be pushed if/when we resume observing in
1262 // |StartObservingRootWindow()|.
1263 if (observing_root_window_
&& should_request_vsync
)
1264 content_view_core_
->GetWindowAndroid()->RequestVSyncUpdate();
1267 void RenderWidgetHostViewAndroid::StartObservingRootWindow() {
1268 DCHECK(content_view_core_
);
1269 if (observing_root_window_
)
1272 observing_root_window_
= true;
1273 content_view_core_
->GetWindowAndroid()->AddObserver(this);
1275 // Clear existing vsync requests to allow a request to the new window.
1276 uint32 outstanding_vsync_requests
= outstanding_vsync_requests_
;
1277 outstanding_vsync_requests_
= 0;
1278 RequestVSyncUpdate(outstanding_vsync_requests
);
1281 void RenderWidgetHostViewAndroid::StopObservingRootWindow() {
1282 if (!content_view_core_
) {
1283 DCHECK(!observing_root_window_
);
1287 if (!observing_root_window_
)
1290 observing_root_window_
= false;
1291 content_view_core_
->GetWindowAndroid()->RemoveObserver(this);
1294 void RenderWidgetHostViewAndroid::SendBeginFrame(base::TimeTicks frame_time
,
1295 base::TimeDelta vsync_period
) {
1296 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::SendBeginFrame");
1297 base::TimeTicks display_time
= frame_time
+ vsync_period
;
1299 // TODO(brianderson): Use adaptive draw-time estimation.
1300 base::TimeDelta estimated_browser_composite_time
=
1301 base::TimeDelta::FromMicroseconds(
1302 (1.0f
* base::Time::kMicrosecondsPerSecond
) / (3.0f
* 60));
1304 base::TimeTicks deadline
= display_time
- estimated_browser_composite_time
;
1306 host_
->Send(new ViewMsg_BeginFrame(
1307 host_
->GetRoutingID(),
1308 cc::BeginFrameArgs::Create(frame_time
, deadline
, vsync_period
)));
1311 bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time
) {
1312 bool needs_animate
=
1313 overscroll_effect_
? overscroll_effect_
->Animate(frame_time
) : false;
1314 if (selection_controller_
)
1315 needs_animate
|= selection_controller_
->Animate(frame_time
);
1316 return needs_animate
;
1319 void RenderWidgetHostViewAndroid::OnContentScrollingChange() {
1320 if (selection_controller_
)
1321 selection_controller_
->SetTemporarilyHidden(IsContentScrolling());
1324 bool RenderWidgetHostViewAndroid::IsContentScrolling() const {
1325 return touch_scrolling_
|| potentially_active_fling_count_
> 0;
1328 void RenderWidgetHostViewAndroid::AcceleratedSurfacePostSubBuffer(
1329 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params
& params
,
1334 void RenderWidgetHostViewAndroid::AcceleratedSurfaceSuspend() {
1338 void RenderWidgetHostViewAndroid::AcceleratedSurfaceRelease() {
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::NATIVE_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 switch (event
.type
) {
1395 case blink::WebInputEvent::GestureScrollBegin
:
1396 touch_scrolling_
= true;
1397 potentially_active_fling_count_
= 0;
1398 OnContentScrollingChange();
1400 case blink::WebInputEvent::GestureScrollEnd
:
1401 touch_scrolling_
= false;
1402 OnContentScrollingChange();
1404 case blink::WebInputEvent::GestureFlingStart
:
1405 touch_scrolling_
= false;
1406 if (ack_result
== INPUT_EVENT_ACK_STATE_CONSUMED
)
1407 ++potentially_active_fling_count_
;
1408 OnContentScrollingChange();
1414 if (content_view_core_
)
1415 content_view_core_
->OnGestureEventAck(event
, ack_result
);
1418 InputEventAckState
RenderWidgetHostViewAndroid::FilterInputEvent(
1419 const blink::WebInputEvent
& input_event
) {
1420 if (selection_controller_
) {
1421 switch (input_event
.type
) {
1422 case blink::WebInputEvent::GestureLongPress
:
1423 selection_controller_
->OnLongPressEvent();
1425 case blink::WebInputEvent::GestureTap
:
1426 selection_controller_
->OnTapEvent();
1433 if (content_view_core_
&&
1434 content_view_core_
->FilterInputEvent(input_event
))
1435 return INPUT_EVENT_ACK_STATE_CONSUMED
;
1438 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED
;
1440 if (input_event
.type
== blink::WebInputEvent::GestureTapDown
||
1441 input_event
.type
== blink::WebInputEvent::TouchStart
) {
1442 GpuDataManagerImpl
* gpu_data
= GpuDataManagerImpl::GetInstance();
1443 GpuProcessHostUIShim
* shim
= GpuProcessHostUIShim::GetOneInstance();
1444 if (shim
&& gpu_data
&& accelerated_surface_route_id_
&&
1445 gpu_data
->IsDriverBugWorkaroundActive(gpu::WAKE_UP_GPU_BEFORE_DRAWING
))
1447 new AcceleratedSurfaceMsg_WakeUpGpu(accelerated_surface_route_id_
));
1450 SynchronousCompositorImpl
* compositor
=
1451 SynchronousCompositorImpl::FromID(host_
->GetProcess()->GetID(),
1452 host_
->GetRoutingID());
1454 return compositor
->HandleInputEvent(input_event
);
1455 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED
;
1458 void RenderWidgetHostViewAndroid::OnSetNeedsFlushInput() {
1459 TRACE_EVENT0("input", "RenderWidgetHostViewAndroid::OnSetNeedsFlushInput");
1460 RequestVSyncUpdate(FLUSH_INPUT
);
1463 BrowserAccessibilityManager
*
1464 RenderWidgetHostViewAndroid::CreateBrowserAccessibilityManager(
1465 BrowserAccessibilityDelegate
* delegate
) {
1466 base::android::ScopedJavaLocalRef
<jobject
> obj
;
1467 if (content_view_core_
)
1468 obj
= content_view_core_
->GetJavaObject();
1469 return new BrowserAccessibilityManagerAndroid(
1471 BrowserAccessibilityManagerAndroid::GetEmptyDocument(),
1475 bool RenderWidgetHostViewAndroid::LockMouse() {
1480 void RenderWidgetHostViewAndroid::UnlockMouse() {
1484 // Methods called from the host to the render
1486 void RenderWidgetHostViewAndroid::SendKeyEvent(
1487 const NativeWebKeyboardEvent
& event
) {
1489 host_
->ForwardKeyboardEvent(event
);
1492 void RenderWidgetHostViewAndroid::SendTouchEvent(
1493 const blink::WebTouchEvent
& event
) {
1495 host_
->ForwardTouchEventWithLatencyInfo(event
, CreateLatencyInfo(event
));
1497 // Send a proactive BeginFrame on the next vsync to reduce latency.
1498 // This is good enough as long as the first touch event has Begin semantics
1499 // and the actual scroll happens on the next vsync.
1500 // TODO: Is this actually still needed?
1501 if (observing_root_window_
)
1502 RequestVSyncUpdate(BEGIN_FRAME
);
1505 void RenderWidgetHostViewAndroid::SendMouseEvent(
1506 const blink::WebMouseEvent
& event
) {
1508 host_
->ForwardMouseEvent(event
);
1511 void RenderWidgetHostViewAndroid::SendMouseWheelEvent(
1512 const blink::WebMouseWheelEvent
& event
) {
1514 host_
->ForwardWheelEvent(event
);
1517 void RenderWidgetHostViewAndroid::SendGestureEvent(
1518 const blink::WebGestureEvent
& event
) {
1519 // Sending a gesture that may trigger overscroll should resume the effect.
1520 if (overscroll_effect_
)
1521 overscroll_effect_
->Enable();
1524 host_
->ForwardGestureEventWithLatencyInfo(event
, CreateLatencyInfo(event
));
1527 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point
& point
) {
1529 host_
->MoveCaret(point
);
1532 void RenderWidgetHostViewAndroid::HideTextHandles() {
1533 if (selection_controller_
)
1534 selection_controller_
->HideAndDisallowShowingAutomatically();
1537 void RenderWidgetHostViewAndroid::OnShowingPastePopup(
1538 const gfx::PointF
& point
) {
1539 if (!selection_controller_
)
1542 // As the paste popup may be triggered *before* the bounds and editability
1543 // of the region have been updated, explicitly set the properties now.
1544 // TODO(jdduke): Remove this workaround when auxiliary paste popup
1545 // notifications are no longer required, crbug.com/398170.
1546 cc::ViewportSelectionBound insertion_bound
;
1547 insertion_bound
.type
= cc::SELECTION_BOUND_CENTER
;
1548 insertion_bound
.visible
= true;
1549 insertion_bound
.edge_top
= point
;
1550 insertion_bound
.edge_bottom
= point
;
1552 ShowSelectionHandlesAutomatically();
1553 selection_controller_
->OnSelectionEditable(true);
1554 selection_controller_
->OnSelectionEmpty(true);
1555 selection_controller_
->OnSelectionBoundsChanged(insertion_bound
,
1559 SkColor
RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const {
1560 return cached_background_color_
;
1563 void RenderWidgetHostViewAndroid::DidOverscroll(
1564 const DidOverscrollParams
& params
) {
1565 if (!content_view_core_
|| !layer_
|| !is_showing_
)
1568 const float device_scale_factor
= content_view_core_
->GetDpiScale();
1570 if (overscroll_effect_
&&
1571 overscroll_effect_
->OnOverscrolled(
1572 content_view_core_
->GetLayer(),
1573 base::TimeTicks::Now(),
1574 gfx::ScaleVector2d(params
.accumulated_overscroll
,
1575 device_scale_factor
),
1576 gfx::ScaleVector2d(params
.latest_overscroll_delta
,
1577 device_scale_factor
),
1578 gfx::ScaleVector2d(params
.current_fling_velocity
,
1579 device_scale_factor
),
1581 params
.causal_event_viewport_point
.OffsetFromOrigin(),
1582 device_scale_factor
))) {
1587 void RenderWidgetHostViewAndroid::DidStopFlinging() {
1588 if (potentially_active_fling_count_
) {
1589 --potentially_active_fling_count_
;
1590 OnContentScrollingChange();
1593 if (content_view_core_
)
1594 content_view_core_
->DidStopFlinging();
1597 void RenderWidgetHostViewAndroid::SetContentViewCore(
1598 ContentViewCoreImpl
* content_view_core
) {
1600 StopObservingRootWindow();
1602 bool resize
= false;
1603 if (content_view_core
!= content_view_core_
) {
1604 overscroll_effect_
.reset();
1605 selection_controller_
.reset();
1606 ReleaseLocksOnSurface();
1610 content_view_core_
= content_view_core
;
1612 BrowserAccessibilityManager
* manager
= NULL
;
1614 manager
= host_
->GetRootBrowserAccessibilityManager();
1616 base::android::ScopedJavaLocalRef
<jobject
> obj
;
1617 if (content_view_core_
)
1618 obj
= content_view_core_
->GetJavaObject();
1619 manager
->ToBrowserAccessibilityManagerAndroid()->SetContentViewCore(obj
);
1624 if (!content_view_core_
)
1627 StartObservingRootWindow();
1632 if (!selection_controller_
)
1633 selection_controller_
.reset(new TouchSelectionController(this));
1635 if (overscroll_effect_enabled_
&& !overscroll_effect_
&&
1636 content_view_core_
->GetWindowAndroid()->GetCompositor())
1637 overscroll_effect_
= CreateOverscrollEffect(content_view_core_
);
1640 void RenderWidgetHostViewAndroid::RunAckCallbacks() {
1641 while (!ack_callbacks_
.empty()) {
1642 ack_callbacks_
.front().Run();
1643 ack_callbacks_
.pop();
1647 void RenderWidgetHostViewAndroid::OnGestureEvent(
1648 const ui::GestureEventData
& gesture
) {
1649 if (gesture_text_selector_
.OnGestureEvent(gesture
))
1652 SendGestureEvent(CreateWebGestureEventFromGestureEventData(gesture
));
1655 void RenderWidgetHostViewAndroid::OnCompositingDidCommit() {
1660 void RenderWidgetHostViewAndroid::OnAttachCompositor() {
1661 DCHECK(content_view_core_
);
1662 if (overscroll_effect_enabled_
&& !overscroll_effect_
)
1663 overscroll_effect_
= CreateOverscrollEffect(content_view_core_
);
1666 void RenderWidgetHostViewAndroid::OnDetachCompositor() {
1667 DCHECK(content_view_core_
);
1668 DCHECK(!using_synchronous_compositor_
);
1670 overscroll_effect_
.reset();
1673 void RenderWidgetHostViewAndroid::OnVSync(base::TimeTicks frame_time
,
1674 base::TimeDelta vsync_period
) {
1675 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::OnVSync");
1679 const uint32 current_vsync_requests
= outstanding_vsync_requests_
;
1680 outstanding_vsync_requests_
= 0;
1682 if (current_vsync_requests
& FLUSH_INPUT
)
1683 host_
->FlushInput();
1685 if (current_vsync_requests
& BEGIN_FRAME
||
1686 current_vsync_requests
& PERSISTENT_BEGIN_FRAME
) {
1687 SendBeginFrame(frame_time
, vsync_period
);
1690 if (current_vsync_requests
& PERSISTENT_BEGIN_FRAME
)
1691 RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME
);
1694 void RenderWidgetHostViewAndroid::OnAnimate(base::TimeTicks begin_frame_time
) {
1695 if (Animate(begin_frame_time
))
1699 void RenderWidgetHostViewAndroid::OnLostResources() {
1700 ReleaseLocksOnSurface();
1702 DestroyDelegatedContent();
1703 DCHECK(ack_callbacks_
.empty());
1704 // We should not loose a frame if we have readback requests pending.
1705 DCHECK(readbacks_waiting_for_frame_
.empty());
1710 RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResultForDelegatedReadback(
1711 const gfx::Size
& dst_size_in_pixel
,
1712 const SkColorType color_type
,
1713 const base::TimeTicks
& start_time
,
1714 scoped_refptr
<cc::Layer
> readback_layer
,
1715 const base::Callback
<void(bool, const SkBitmap
&)>& callback
,
1716 scoped_ptr
<cc::CopyOutputResult
> result
) {
1717 readback_layer
->RemoveFromParent();
1718 PrepareTextureCopyOutputResult(
1719 dst_size_in_pixel
, color_type
, start_time
, callback
, result
.Pass());
1723 void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
1724 const gfx::Size
& dst_size_in_pixel
,
1725 const SkColorType color_type
,
1726 const base::TimeTicks
& start_time
,
1727 const base::Callback
<void(bool, const SkBitmap
&)>& callback
,
1728 scoped_ptr
<cc::CopyOutputResult
> result
) {
1729 base::ScopedClosureRunner
scoped_callback_runner(
1730 base::Bind(callback
, false, SkBitmap()));
1732 "RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult");
1734 if (!result
->HasTexture() || result
->IsEmpty() || result
->size().IsEmpty())
1737 scoped_ptr
<SkBitmap
> bitmap(new SkBitmap
);
1738 if (!bitmap
->allocPixels(SkImageInfo::Make(dst_size_in_pixel
.width(),
1739 dst_size_in_pixel
.height(),
1741 kOpaque_SkAlphaType
)))
1744 ImageTransportFactoryAndroid
* factory
=
1745 ImageTransportFactoryAndroid::GetInstance();
1746 GLHelper
* gl_helper
= factory
->GetGLHelper();
1751 scoped_ptr
<SkAutoLockPixels
> bitmap_pixels_lock(
1752 new SkAutoLockPixels(*bitmap
));
1753 uint8
* pixels
= static_cast<uint8
*>(bitmap
->getPixels());
1755 cc::TextureMailbox texture_mailbox
;
1756 scoped_ptr
<cc::SingleReleaseCallback
> release_callback
;
1757 result
->TakeTexture(&texture_mailbox
, &release_callback
);
1758 DCHECK(texture_mailbox
.IsTexture());
1759 if (!texture_mailbox
.IsTexture())
1762 ignore_result(scoped_callback_runner
.Release());
1764 gl_helper
->CropScaleReadbackAndCleanMailbox(
1765 texture_mailbox
.mailbox(),
1766 texture_mailbox
.sync_point(),
1768 gfx::Rect(result
->size()),
1772 base::Bind(&CopyFromCompositingSurfaceFinished
,
1774 base::Passed(&release_callback
),
1775 base::Passed(&bitmap
),
1777 base::Passed(&bitmap_pixels_lock
)),
1778 GLHelper::SCALER_QUALITY_GOOD
);
1781 bool RenderWidgetHostViewAndroid::IsReadbackConfigSupported(
1782 SkColorType color_type
) {
1783 ImageTransportFactoryAndroid
* factory
=
1784 ImageTransportFactoryAndroid::GetInstance();
1785 GLHelper
* gl_helper
= factory
->GetGLHelper();
1788 return gl_helper
->IsReadbackConfigSupported(color_type
);
1791 SkColorType
RenderWidgetHostViewAndroid::PreferredReadbackFormat() {
1792 // Define the criteria here. If say the 16 texture readback is
1793 // supported we should go with that (this degrades quality)
1794 // or stick back to the default format.
1795 if (base::SysInfo::IsLowEndDevice()) {
1796 if (IsReadbackConfigSupported(kRGB_565_SkColorType
))
1797 return kRGB_565_SkColorType
;
1799 return kN32_SkColorType
;
1802 void RenderWidgetHostViewAndroid::ShowSelectionHandlesAutomatically() {
1803 // Fake a long press to allow automatic selection handle showing.
1804 if (selection_controller_
)
1805 selection_controller_
->OnLongPressEvent();
1808 void RenderWidgetHostViewAndroid::SelectRange(
1809 float x1
, float y1
, float x2
, float y2
) {
1810 if (content_view_core_
)
1811 static_cast<WebContentsImpl
*>(content_view_core_
->GetWebContents())->
1812 SelectRange(gfx::Point(x1
, y1
), gfx::Point(x2
, y2
));
1815 void RenderWidgetHostViewAndroid::Unselect() {
1816 if (content_view_core_
)
1817 content_view_core_
->GetWebContents()->Unselect();
1820 void RenderWidgetHostViewAndroid::LongPress(
1821 base::TimeTicks time
, float x
, float y
) {
1822 blink::WebGestureEvent long_press
= WebGestureEventBuilder::Build(
1823 blink::WebInputEvent::GestureLongPress
,
1824 (time
- base::TimeTicks()).InSecondsF(), x
, y
);
1825 SendGestureEvent(long_press
);
1829 void RenderWidgetHostViewBase::GetDefaultScreenInfo(
1830 blink::WebScreenInfo
* results
) {
1831 const gfx::Display
& display
=
1832 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
1833 results
->rect
= display
.bounds();
1834 // TODO(husky): Remove any system controls from availableRect.
1835 results
->availableRect
= display
.work_area();
1836 results
->deviceScaleFactor
= display
.device_scale_factor();
1837 results
->orientationAngle
= display
.RotationAsDegree();
1838 results
->orientationType
=
1839 RenderWidgetHostViewBase::GetOrientationTypeForMobile(display
);
1840 gfx::DeviceDisplayInfo info
;
1841 results
->depth
= info
.GetBitsPerPixel();
1842 results
->depthPerComponent
= info
.GetBitsPerComponent();
1843 results
->isMonochrome
= (results
->depthPerComponent
== 0);
1846 } // namespace content