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. 4 5 #include "content/browser/renderer_host/render_widget_host_view_android.h" 6 7 #include <android/bitmap.h> 8 9 #include "base/android/build_info.h" 10 #include "base/basictypes.h" 11 #include "base/bind.h" 12 #include "base/callback_helpers.h" 13 #include "base/command_line.h" 14 #include "base/logging.h" 15 #include "base/message_loop/message_loop.h" 16 #include "base/metrics/histogram.h" 17 #include "base/strings/utf_string_conversions.h" 18 #include "base/sys_info.h" 19 #include "base/threading/worker_pool.h" 20 #include "cc/base/latency_info_swap_promise.h" 21 #include "cc/layers/delegated_frame_provider.h" 22 #include "cc/layers/delegated_renderer_layer.h" 23 #include "cc/layers/layer.h" 24 #include "cc/output/compositor_frame.h" 25 #include "cc/output/compositor_frame_ack.h" 26 #include "cc/output/copy_output_request.h" 27 #include "cc/output/copy_output_result.h" 28 #include "cc/output/viewport_selection_bound.h" 29 #include "cc/resources/single_release_callback.h" 30 #include "cc/trees/layer_tree_host.h" 31 #include "content/browser/accessibility/browser_accessibility_manager_android.h" 32 #include "content/browser/android/composited_touch_handle_drawable.h" 33 #include "content/browser/android/content_view_core_impl.h" 34 #include "content/browser/android/edge_effect.h" 35 #include "content/browser/android/edge_effect_l.h" 36 #include "content/browser/android/in_process/synchronous_compositor_impl.h" 37 #include "content/browser/android/overscroll_glow.h" 38 #include "content/browser/devtools/render_view_devtools_agent_host.h" 39 #include "content/browser/gpu/compositor_util.h" 40 #include "content/browser/gpu/gpu_data_manager_impl.h" 41 #include "content/browser/gpu/gpu_process_host_ui_shim.h" 42 #include "content/browser/gpu/gpu_surface_tracker.h" 43 #include "content/browser/media/media_web_contents_observer.h" 44 #include "content/browser/renderer_host/compositor_impl_android.h" 45 #include "content/browser/renderer_host/dip_util.h" 46 #include "content/browser/renderer_host/image_transport_factory_android.h" 47 #include "content/browser/renderer_host/input/synthetic_gesture_target_android.h" 48 #include "content/browser/renderer_host/input/touch_selection_controller.h" 49 #include "content/browser/renderer_host/input/web_input_event_builders_android.h" 50 #include "content/browser/renderer_host/input/web_input_event_util.h" 51 #include "content/browser/renderer_host/render_process_host_impl.h" 52 #include "content/browser/renderer_host/render_view_host_impl.h" 53 #include "content/browser/renderer_host/render_widget_host_impl.h" 54 #include "content/common/gpu/client/gl_helper.h" 55 #include "content/common/gpu/gpu_messages.h" 56 #include "content/common/input/did_overscroll_params.h" 57 #include "content/common/input_messages.h" 58 #include "content/common/view_messages.h" 59 #include "content/public/browser/browser_thread.h" 60 #include "content/public/browser/devtools_agent_host.h" 61 #include "content/public/browser/render_view_host.h" 62 #include "content/public/common/content_switches.h" 63 #include "gpu/command_buffer/client/gles2_interface.h" 64 #include "gpu/config/gpu_driver_bug_workaround_type.h" 65 #include "skia/ext/image_operations.h" 66 #include "third_party/khronos/GLES2/gl2.h" 67 #include "third_party/khronos/GLES2/gl2ext.h" 68 #include "third_party/skia/include/core/SkCanvas.h" 69 #include "ui/base/android/window_android.h" 70 #include "ui/base/android/window_android_compositor.h" 71 #include "ui/events/gesture_detection/gesture_config_helper.h" 72 #include "ui/events/gesture_detection/motion_event.h" 73 #include "ui/gfx/android/device_display_info.h" 74 #include "ui/gfx/android/java_bitmap.h" 75 #include "ui/gfx/android/view_configuration.h" 76 #include "ui/gfx/display.h" 77 #include "ui/gfx/screen.h" 78 #include "ui/gfx/size_conversions.h" 79 80 namespace content { 81 82 namespace { 83 84 const int kUndefinedOutputSurfaceId = -1; 85 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; 90 91 // Used for conditional creation of EdgeEffect types for overscroll. 92 const int kKitKatMR2SDKVersion = 19; 93 94 static const char kAsyncReadBackString[] = "Compositing.CopyFromSurfaceTime"; 95 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())); 99 } 100 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, 107 bool result) { 108 TRACE_EVENT0( 109 "cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceFinished"); 110 bitmap_pixels_lock.reset(); 111 uint32 sync_point = 0; 112 if (result) { 113 GLHelper* gl_helper = 114 ImageTransportFactoryAndroid::GetInstance()->GetGLHelper(); 115 sync_point = gl_helper->InsertSyncPoint(); 116 } 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); 122 } 123 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, 132 0, 133 0, 134 base::TimeTicks() + base::TimeDelta::FromMicroseconds(time_micros), 135 1); 136 } 137 return latency_info; 138 } 139 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; 144 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()) * 159 scale_factor; 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()) * 164 scale_factor; 165 166 return params; 167 } 168 169 bool UseEdgeEffectL() { 170 static bool use_edge_effect_l = 171 base::android::BuildInfo::GetInstance()->sdk_int() > kKitKatMR2SDKVersion; 172 return use_edge_effect_l; 173 } 174 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)); 181 182 return scoped_ptr<EdgeEffectBase>( 183 new EdgeEffect(resource_manager, device_scale_factor)); 184 } 185 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(); 191 DCHECK(compositor); 192 ui::SystemUIResourceManager* system_resource_manager = 193 &compositor->GetSystemUIResourceManager(); 194 195 if (UseEdgeEffectL()) 196 EdgeEffectL::PreloadResources(system_resource_manager); 197 else 198 EdgeEffect::PreloadResources(system_resource_manager); 199 200 return make_scoped_ptr( 201 new OverscrollGlow(base::Bind(&CreateEdgeEffect, 202 system_resource_manager, 203 content_view_core->GetDpiScale()))); 204 } 205 206 scoped_ptr<TouchSelectionController> CreateSelectionController( 207 TouchSelectionControllerClient* client, 208 ContentViewCore* content_view_core) { 209 DCHECK(client); 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( 214 client, 215 base::TimeDelta::FromMilliseconds(tap_timeout_ms), 216 touch_slop_pixels / content_view_core->GetDpiScale())); 217 } 218 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); 224 return config; 225 } 226 227 bool HasFixedPageScale(const cc::CompositorFrameMetadata& frame_metadata) { 228 return frame_metadata.min_page_scale_factor == 229 frame_metadata.max_page_scale_factor; 230 } 231 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; 238 } 239 240 } // anonymous namespace 241 242 ReadbackRequest::ReadbackRequest( 243 float scale, 244 SkColorType color_type, 245 gfx::Rect src_subrect, 246 const base::Callback<void(bool, const SkBitmap&)>& result_callback) 247 : scale_(scale), 248 color_type_(color_type), 249 src_subrect_(src_subrect), 250 result_callback_(result_callback) { 251 } 252 253 ReadbackRequest::ReadbackRequest() { 254 } 255 256 ReadbackRequest::~ReadbackRequest() { 257 } 258 259 RenderWidgetHostViewAndroid::LastFrameInfo::LastFrameInfo( 260 uint32 output_id, 261 scoped_ptr<cc::CompositorFrame> output_frame) 262 : output_surface_id(output_id), frame(output_frame.Pass()) {} 263 264 RenderWidgetHostViewAndroid::LastFrameInfo::~LastFrameInfo() {} 265 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_browser_compositor_(CompositorImpl::IsInitialized()), 283 frame_evictor_(new DelegatedFrameEvictor(this)), 284 locks_on_frame_count_(0), 285 observing_root_window_(false), 286 weak_ptr_factory_(this) { 287 host_->SetView(this); 288 SetContentViewCore(content_view_core); 289 ImageTransportFactoryAndroid::AddObserver(this); 290 } 291 292 RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() { 293 ImageTransportFactoryAndroid::RemoveObserver(this); 294 SetContentViewCore(NULL); 295 DCHECK(ack_callbacks_.empty()); 296 DCHECK(readbacks_waiting_for_frame_.empty()); 297 if (resource_collection_.get()) 298 resource_collection_->SetClient(NULL); 299 } 300 301 302 bool RenderWidgetHostViewAndroid::OnMessageReceived( 303 const IPC::Message& message) { 304 bool handled = true; 305 IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAndroid, message) 306 IPC_MESSAGE_HANDLER(ViewHostMsg_StartContentIntent, OnStartContentIntent) 307 IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeBodyBackgroundColor, 308 OnDidChangeBodyBackgroundColor) 309 IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrame, 310 OnSetNeedsBeginFrame) 311 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged, 312 OnTextInputStateChanged) 313 IPC_MESSAGE_HANDLER(ViewHostMsg_SmartClipDataExtracted, 314 OnSmartClipDataExtracted) 315 IPC_MESSAGE_UNHANDLED(handled = false) 316 IPC_END_MESSAGE_MAP() 317 return handled; 318 } 319 320 void RenderWidgetHostViewAndroid::InitAsChild(gfx::NativeView parent_view) { 321 NOTIMPLEMENTED(); 322 } 323 324 void RenderWidgetHostViewAndroid::InitAsPopup( 325 RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) { 326 NOTIMPLEMENTED(); 327 } 328 329 void RenderWidgetHostViewAndroid::InitAsFullscreen( 330 RenderWidgetHostView* reference_host_view) { 331 NOTIMPLEMENTED(); 332 } 333 334 RenderWidgetHost* 335 RenderWidgetHostViewAndroid::GetRenderWidgetHost() const { 336 return host_; 337 } 338 339 void RenderWidgetHostViewAndroid::WasShown() { 340 if (!host_ || !host_->is_hidden()) 341 return; 342 343 host_->WasShown(ui::LatencyInfo()); 344 345 if (content_view_core_) { 346 StartObservingRootWindow(); 347 RequestVSyncUpdate(BEGIN_FRAME); 348 } 349 } 350 351 void RenderWidgetHostViewAndroid::WasHidden() { 352 RunAckCallbacks(); 353 354 if (!host_ || host_->is_hidden()) 355 return; 356 357 // Inform the renderer that we are being hidden so it can reduce its resource 358 // utilization. 359 host_->WasHidden(); 360 361 StopObservingRootWindow(); 362 } 363 364 void RenderWidgetHostViewAndroid::WasResized() { 365 host_->WasResized(); 366 } 367 368 void RenderWidgetHostViewAndroid::SetSize(const gfx::Size& size) { 369 // Ignore the given size as only the Java code has the power to 370 // resize the view on Android. 371 default_size_ = size; 372 } 373 374 void RenderWidgetHostViewAndroid::SetBounds(const gfx::Rect& rect) { 375 SetSize(rect.size()); 376 } 377 378 void RenderWidgetHostViewAndroid::AbortPendingReadbackRequests() { 379 while (!readbacks_waiting_for_frame_.empty()) { 380 ReadbackRequest& readback_request = readbacks_waiting_for_frame_.front(); 381 readback_request.GetResultCallback().Run(false, SkBitmap()); 382 readbacks_waiting_for_frame_.pop(); 383 } 384 } 385 386 void RenderWidgetHostViewAndroid::GetScaledContentBitmap( 387 float scale, 388 SkColorType color_type, 389 gfx::Rect src_subrect, 390 CopyFromCompositingSurfaceCallback& result_callback) { 391 if (!host_ || host_->is_hidden()) { 392 result_callback.Run(false, SkBitmap()); 393 return; 394 } 395 if (!IsSurfaceAvailableForCopy()) { 396 // The view is visible, probably the frame has not yet arrived. 397 // Just add the ReadbackRequest to queue and wait for frame arrival 398 // to get this request processed. 399 readbacks_waiting_for_frame_.push( 400 ReadbackRequest(scale, color_type, src_subrect, result_callback)); 401 return; 402 } 403 404 gfx::Size bounds = layer_->bounds(); 405 if (src_subrect.IsEmpty()) 406 src_subrect = gfx::Rect(bounds); 407 DCHECK_LE(src_subrect.width() + src_subrect.x(), bounds.width()); 408 DCHECK_LE(src_subrect.height() + src_subrect.y(), bounds.height()); 409 const gfx::Display& display = 410 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay(); 411 float device_scale_factor = display.device_scale_factor(); 412 DCHECK_GT(device_scale_factor, 0); 413 gfx::Size dst_size( 414 gfx::ToCeiledSize(gfx::ScaleSize(bounds, scale / device_scale_factor))); 415 CopyFromCompositingSurface( 416 src_subrect, dst_size, result_callback, color_type); 417 } 418 419 scoped_refptr<cc::DelegatedRendererLayer> 420 RenderWidgetHostViewAndroid::CreateDelegatedLayerForFrameProvider() const { 421 DCHECK(frame_provider_); 422 423 scoped_refptr<cc::DelegatedRendererLayer> delegated_layer = 424 cc::DelegatedRendererLayer::Create(frame_provider_); 425 delegated_layer->SetBounds(content_size_in_layer_); 426 delegated_layer->SetIsDrawable(true); 427 delegated_layer->SetContentsOpaque(true); 428 429 return delegated_layer; 430 } 431 432 bool RenderWidgetHostViewAndroid::HasValidFrame() const { 433 if (!content_view_core_) 434 return false; 435 if (!layer_) 436 return false; 437 438 if (texture_size_in_layer_.IsEmpty()) 439 return false; 440 // This tell us whether a valid frame has arrived or not. 441 if (!frame_evictor_->HasFrame()) 442 return false; 443 444 return true; 445 } 446 447 gfx::Vector2dF RenderWidgetHostViewAndroid::GetLastScrollOffset() const { 448 return last_scroll_offset_; 449 } 450 451 gfx::NativeView RenderWidgetHostViewAndroid::GetNativeView() const { 452 return content_view_core_->GetViewAndroid(); 453 } 454 455 gfx::NativeViewId RenderWidgetHostViewAndroid::GetNativeViewId() const { 456 return reinterpret_cast<gfx::NativeViewId>( 457 const_cast<RenderWidgetHostViewAndroid*>(this)); 458 } 459 460 gfx::NativeViewAccessible 461 RenderWidgetHostViewAndroid::GetNativeViewAccessible() { 462 NOTIMPLEMENTED(); 463 return NULL; 464 } 465 466 void RenderWidgetHostViewAndroid::MovePluginWindows( 467 const std::vector<WebPluginGeometry>& moves) { 468 // We don't have plugin windows on Android. Do nothing. Note: this is called 469 // from RenderWidgetHost::OnUpdateRect which is itself invoked while 470 // processing the corresponding message from Renderer. 471 } 472 473 void RenderWidgetHostViewAndroid::Focus() { 474 host_->Focus(); 475 host_->SetInputMethodActive(true); 476 if (overscroll_effect_) 477 overscroll_effect_->Enable(); 478 } 479 480 void RenderWidgetHostViewAndroid::Blur() { 481 host_->SetInputMethodActive(false); 482 host_->Blur(); 483 if (overscroll_effect_) 484 overscroll_effect_->Disable(); 485 } 486 487 bool RenderWidgetHostViewAndroid::HasFocus() const { 488 if (!content_view_core_) 489 return false; // ContentViewCore not created yet. 490 491 return content_view_core_->HasFocus(); 492 } 493 494 bool RenderWidgetHostViewAndroid::IsSurfaceAvailableForCopy() const { 495 return HasValidFrame(); 496 } 497 498 void RenderWidgetHostViewAndroid::Show() { 499 if (is_showing_) 500 return; 501 502 is_showing_ = true; 503 if (layer_) 504 layer_->SetHideLayerAndSubtree(false); 505 506 frame_evictor_->SetVisible(true); 507 WasShown(); 508 } 509 510 void RenderWidgetHostViewAndroid::Hide() { 511 if (!is_showing_) 512 return; 513 514 is_showing_ = false; 515 if (layer_ && locks_on_frame_count_ == 0) 516 layer_->SetHideLayerAndSubtree(true); 517 518 frame_evictor_->SetVisible(false); 519 // We don't know if we will ever get a frame if we are hiding the renderer, so 520 // we need to cancel all requests 521 AbortPendingReadbackRequests(); 522 WasHidden(); 523 } 524 525 bool RenderWidgetHostViewAndroid::IsShowing() { 526 // ContentViewCoreImpl represents the native side of the Java 527 // ContentViewCore. It being NULL means that it is not attached 528 // to the View system yet, so we treat this RWHVA as hidden. 529 return is_showing_ && content_view_core_; 530 } 531 532 void RenderWidgetHostViewAndroid::LockCompositingSurface() { 533 DCHECK(HasValidFrame()); 534 DCHECK(host_); 535 DCHECK(frame_evictor_->HasFrame()); 536 frame_evictor_->LockFrame(); 537 locks_on_frame_count_++; 538 } 539 540 void RenderWidgetHostViewAndroid::UnlockCompositingSurface() { 541 if (!frame_evictor_->HasFrame() || locks_on_frame_count_ == 0) 542 return; 543 544 DCHECK(HasValidFrame()); 545 frame_evictor_->UnlockFrame(); 546 locks_on_frame_count_--; 547 548 if (locks_on_frame_count_ == 0) { 549 if (last_frame_info_) { 550 InternalSwapCompositorFrame(last_frame_info_->output_surface_id, 551 last_frame_info_->frame.Pass()); 552 last_frame_info_.reset(); 553 } 554 555 if (!is_showing_ && layer_) 556 layer_->SetHideLayerAndSubtree(true); 557 } 558 } 559 560 void RenderWidgetHostViewAndroid::SetTextSurroundingSelectionCallback( 561 const TextSurroundingSelectionCallback& callback) { 562 // Only one outstanding request is allowed at any given time. 563 DCHECK(!callback.is_null()); 564 text_surrounding_selection_callback_ = callback; 565 } 566 567 void RenderWidgetHostViewAndroid::OnTextSurroundingSelectionResponse( 568 const base::string16& content, 569 size_t start_offset, 570 size_t end_offset) { 571 if (text_surrounding_selection_callback_.is_null()) 572 return; 573 text_surrounding_selection_callback_.Run(content, start_offset, end_offset); 574 text_surrounding_selection_callback_.Reset(); 575 } 576 577 void RenderWidgetHostViewAndroid::ReleaseLocksOnSurface() { 578 if (!frame_evictor_->HasFrame()) { 579 DCHECK_EQ(locks_on_frame_count_, 0u); 580 return; 581 } 582 while (locks_on_frame_count_ > 0) { 583 UnlockCompositingSurface(); 584 } 585 RunAckCallbacks(); 586 } 587 588 gfx::Rect RenderWidgetHostViewAndroid::GetViewBounds() const { 589 if (!content_view_core_) 590 return gfx::Rect(default_size_); 591 592 return gfx::Rect(content_view_core_->GetViewSize()); 593 } 594 595 gfx::Size RenderWidgetHostViewAndroid::GetPhysicalBackingSize() const { 596 if (!content_view_core_) 597 return gfx::Size(); 598 599 return content_view_core_->GetPhysicalBackingSize(); 600 } 601 602 float RenderWidgetHostViewAndroid::GetTopControlsLayoutHeight() const { 603 if (!content_view_core_) 604 return 0.f; 605 606 // The amount that the viewport size given to Blink is shrunk by the URL-bar. 607 return content_view_core_->GetTopControlsLayoutHeightDip(); 608 } 609 610 void RenderWidgetHostViewAndroid::UpdateCursor(const WebCursor& cursor) { 611 // There are no cursors on Android. 612 } 613 614 void RenderWidgetHostViewAndroid::SetIsLoading(bool is_loading) { 615 // Do nothing. The UI notification is handled through ContentViewClient which 616 // is TabContentsDelegate. 617 } 618 619 void RenderWidgetHostViewAndroid::TextInputTypeChanged( 620 ui::TextInputType type, 621 ui::TextInputMode input_mode, 622 bool can_compose_inline) { 623 // Unused on Android, which uses OnTextInputChanged instead. 624 } 625 626 long RenderWidgetHostViewAndroid::GetNativeImeAdapter() { 627 return reinterpret_cast<intptr_t>(&ime_adapter_android_); 628 } 629 630 void RenderWidgetHostViewAndroid::OnTextInputStateChanged( 631 const ViewHostMsg_TextInputState_Params& params) { 632 if (selection_controller_) { 633 // This call is semi-redundant with that in |OnFocusedNodeChanged|. The 634 // latter is guaranteed to be called before |OnSelectionBoundsChanged|, 635 // while this call is present to ensure consistency with IME after 636 // navigation and tab focus changes 637 const bool is_editable_node = params.type != ui::TEXT_INPUT_TYPE_NONE; 638 selection_controller_->OnSelectionEditable(is_editable_node); 639 } 640 641 // If the change is not originated from IME (e.g. Javascript, autofill), 642 // send back the renderer an acknowledgement, regardless of how we exit from 643 // this method. 644 base::ScopedClosureRunner ack_caller; 645 if (params.is_non_ime_change) 646 ack_caller.Reset(base::Bind(&SendImeEventAck, host_)); 647 648 if (!IsShowing()) 649 return; 650 651 content_view_core_->UpdateImeAdapter( 652 GetNativeImeAdapter(), 653 static_cast<int>(params.type), params.flags, 654 params.value, params.selection_start, params.selection_end, 655 params.composition_start, params.composition_end, 656 params.show_ime_if_needed, params.is_non_ime_change); 657 } 658 659 void RenderWidgetHostViewAndroid::OnDidChangeBodyBackgroundColor( 660 SkColor color) { 661 if (cached_background_color_ == color) 662 return; 663 664 cached_background_color_ = color; 665 if (content_view_core_) 666 content_view_core_->OnBackgroundColorChanged(color); 667 } 668 669 void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame(bool enabled) { 670 DCHECK(using_browser_compositor_); 671 TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame", 672 "enabled", enabled); 673 if (enabled) 674 RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME); 675 else 676 outstanding_vsync_requests_ &= ~PERSISTENT_BEGIN_FRAME; 677 } 678 679 void RenderWidgetHostViewAndroid::OnStartContentIntent( 680 const GURL& content_url) { 681 if (content_view_core_) 682 content_view_core_->StartContentIntent(content_url); 683 } 684 685 void RenderWidgetHostViewAndroid::OnSmartClipDataExtracted( 686 const base::string16& text, 687 const base::string16& html, 688 const gfx::Rect rect) { 689 if (content_view_core_) 690 content_view_core_->OnSmartClipDataExtracted(text, html, rect); 691 } 692 693 bool RenderWidgetHostViewAndroid::OnTouchEvent( 694 const ui::MotionEvent& event) { 695 if (!host_) 696 return false; 697 698 if (selection_controller_ && 699 selection_controller_->WillHandleTouchEvent(event)) 700 return true; 701 702 if (!gesture_provider_.OnTouchEvent(event)) 703 return false; 704 705 if (gesture_text_selector_.OnTouchEvent(event)) { 706 gesture_provider_.OnTouchEventAck(false); 707 return true; 708 } 709 710 if (host_->ShouldForwardTouchEvent()) { 711 blink::WebTouchEvent web_event = CreateWebTouchEventFromMotionEvent(event); 712 host_->ForwardTouchEventWithLatencyInfo(web_event, 713 CreateLatencyInfo(web_event)); 714 } else { 715 const bool event_consumed = false; 716 gesture_provider_.OnTouchEventAck(event_consumed); 717 } 718 719 // Send a proactive BeginFrame on the next vsync to reduce latency. 720 // This is good enough as long as the first touch event has Begin semantics 721 // and the actual scroll happens on the next vsync. 722 if (observing_root_window_) 723 RequestVSyncUpdate(BEGIN_FRAME); 724 725 return true; 726 } 727 728 bool RenderWidgetHostViewAndroid::OnTouchHandleEvent( 729 const ui::MotionEvent& event) { 730 return selection_controller_ && 731 selection_controller_->WillHandleTouchEvent(event); 732 } 733 734 void RenderWidgetHostViewAndroid::ResetGestureDetection() { 735 const ui::MotionEvent* current_down_event = 736 gesture_provider_.GetCurrentDownEvent(); 737 if (!current_down_event) 738 return; 739 740 scoped_ptr<ui::MotionEvent> cancel_event = current_down_event->Cancel(); 741 DCHECK(cancel_event); 742 OnTouchEvent(*cancel_event); 743 } 744 745 void RenderWidgetHostViewAndroid::SetDoubleTapSupportEnabled(bool enabled) { 746 gesture_provider_.SetDoubleTapSupportForPlatformEnabled(enabled); 747 } 748 749 void RenderWidgetHostViewAndroid::SetMultiTouchZoomSupportEnabled( 750 bool enabled) { 751 gesture_provider_.SetMultiTouchZoomSupportEnabled(enabled); 752 } 753 754 void RenderWidgetHostViewAndroid::ImeCancelComposition() { 755 ime_adapter_android_.CancelComposition(); 756 } 757 758 void RenderWidgetHostViewAndroid::FocusedNodeChanged(bool is_editable_node) { 759 ime_adapter_android_.FocusedNodeChanged(is_editable_node); 760 if (selection_controller_) 761 selection_controller_->OnSelectionEditable(is_editable_node); 762 } 763 764 void RenderWidgetHostViewAndroid::RenderProcessGone( 765 base::TerminationStatus status, int error_code) { 766 Destroy(); 767 } 768 769 void RenderWidgetHostViewAndroid::Destroy() { 770 RemoveLayers(); 771 SetContentViewCore(NULL); 772 773 // The RenderWidgetHost's destruction led here, so don't call it. 774 host_ = NULL; 775 776 delete this; 777 } 778 779 void RenderWidgetHostViewAndroid::SetTooltipText( 780 const base::string16& tooltip_text) { 781 // Tooltips don't makes sense on Android. 782 } 783 784 void RenderWidgetHostViewAndroid::SelectionChanged(const base::string16& text, 785 size_t offset, 786 const gfx::Range& range) { 787 RenderWidgetHostViewBase::SelectionChanged(text, offset, range); 788 789 if (selection_controller_) 790 selection_controller_->OnSelectionEmpty(text.empty()); 791 792 if (!content_view_core_) 793 return; 794 if (range.is_empty()) { 795 content_view_core_->OnSelectionChanged(""); 796 return; 797 } 798 799 DCHECK(!text.empty()); 800 size_t pos = range.GetMin() - offset; 801 size_t n = range.length(); 802 803 DCHECK(pos + n <= text.length()) << "The text can not fully cover range."; 804 if (pos >= text.length()) { 805 NOTREACHED() << "The text can not cover range."; 806 return; 807 } 808 809 std::string utf8_selection = base::UTF16ToUTF8(text.substr(pos, n)); 810 811 content_view_core_->OnSelectionChanged(utf8_selection); 812 } 813 814 void RenderWidgetHostViewAndroid::SelectionBoundsChanged( 815 const ViewHostMsg_SelectionBounds_Params& params) { 816 NOTREACHED() << "Selection bounds should be routed through the compositor."; 817 } 818 819 void RenderWidgetHostViewAndroid::SetBackgroundOpaque(bool opaque) { 820 RenderWidgetHostViewBase::SetBackgroundOpaque(opaque); 821 host_->SetBackgroundOpaque(opaque); 822 } 823 824 void RenderWidgetHostViewAndroid::CopyFromCompositingSurface( 825 const gfx::Rect& src_subrect, 826 const gfx::Size& dst_size, 827 CopyFromCompositingSurfaceCallback& callback, 828 const SkColorType color_type) { 829 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurface"); 830 if ((!host_ || host_->is_hidden()) || 831 !IsReadbackConfigSupported(color_type)) { 832 callback.Run(false, SkBitmap()); 833 return; 834 } 835 base::TimeTicks start_time = base::TimeTicks::Now(); 836 if (using_browser_compositor_ && !IsSurfaceAvailableForCopy()) { 837 callback.Run(false, SkBitmap()); 838 return; 839 } 840 const gfx::Display& display = 841 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay(); 842 float device_scale_factor = display.device_scale_factor(); 843 gfx::Size dst_size_in_pixel = 844 ConvertRectToPixel(device_scale_factor, gfx::Rect(dst_size)).size(); 845 gfx::Rect src_subrect_in_pixel = 846 ConvertRectToPixel(device_scale_factor, src_subrect); 847 848 if (!using_browser_compositor_) { 849 SynchronousCopyContents(src_subrect_in_pixel, dst_size_in_pixel, callback, 850 color_type); 851 UMA_HISTOGRAM_TIMES("Compositing.CopyFromSurfaceTimeSynchronous", 852 base::TimeTicks::Now() - start_time); 853 return; 854 } 855 856 scoped_ptr<cc::CopyOutputRequest> request; 857 scoped_refptr<cc::Layer> readback_layer; 858 DCHECK(content_view_core_); 859 DCHECK(content_view_core_->GetWindowAndroid()); 860 ui::WindowAndroidCompositor* compositor = 861 content_view_core_->GetWindowAndroid()->GetCompositor(); 862 DCHECK(compositor); 863 DCHECK(frame_provider_); 864 scoped_refptr<cc::DelegatedRendererLayer> delegated_layer = 865 CreateDelegatedLayerForFrameProvider(); 866 delegated_layer->SetHideLayerAndSubtree(true); 867 compositor->AttachLayerForReadback(delegated_layer); 868 869 readback_layer = delegated_layer; 870 request = cc::CopyOutputRequest::CreateRequest( 871 base::Bind(&RenderWidgetHostViewAndroid:: 872 PrepareTextureCopyOutputResultForDelegatedReadback, 873 dst_size_in_pixel, 874 color_type, 875 start_time, 876 readback_layer, 877 callback)); 878 request->set_area(src_subrect_in_pixel); 879 readback_layer->RequestCopyOfOutput(request.Pass()); 880 } 881 882 void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame( 883 const gfx::Rect& src_subrect, 884 const scoped_refptr<media::VideoFrame>& target, 885 const base::Callback<void(bool)>& callback) { 886 NOTIMPLEMENTED(); 887 callback.Run(false); 888 } 889 890 bool RenderWidgetHostViewAndroid::CanCopyToVideoFrame() const { 891 return false; 892 } 893 894 void RenderWidgetHostViewAndroid::ShowDisambiguationPopup( 895 const gfx::Rect& rect_pixels, const SkBitmap& zoomed_bitmap) { 896 if (!content_view_core_) 897 return; 898 899 content_view_core_->ShowDisambiguationPopup(rect_pixels, zoomed_bitmap); 900 } 901 902 scoped_ptr<SyntheticGestureTarget> 903 RenderWidgetHostViewAndroid::CreateSyntheticGestureTarget() { 904 return scoped_ptr<SyntheticGestureTarget>(new SyntheticGestureTargetAndroid( 905 host_, content_view_core_->CreateTouchEventSynthesizer())); 906 } 907 908 void RenderWidgetHostViewAndroid::SendDelegatedFrameAck( 909 uint32 output_surface_id) { 910 DCHECK(host_); 911 cc::CompositorFrameAck ack; 912 if (resource_collection_.get()) 913 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources); 914 RenderWidgetHostImpl::SendSwapCompositorFrameAck(host_->GetRoutingID(), 915 output_surface_id, 916 host_->GetProcess()->GetID(), 917 ack); 918 } 919 920 void RenderWidgetHostViewAndroid::SendReturnedDelegatedResources( 921 uint32 output_surface_id) { 922 DCHECK(resource_collection_); 923 924 cc::CompositorFrameAck ack; 925 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources); 926 DCHECK(!ack.resources.empty()); 927 928 RenderWidgetHostImpl::SendReclaimCompositorResources( 929 host_->GetRoutingID(), 930 output_surface_id, 931 host_->GetProcess()->GetID(), 932 ack); 933 } 934 935 void RenderWidgetHostViewAndroid::UnusedResourcesAreAvailable() { 936 if (ack_callbacks_.size()) 937 return; 938 SendReturnedDelegatedResources(last_output_surface_id_); 939 } 940 941 void RenderWidgetHostViewAndroid::DestroyDelegatedContent() { 942 RemoveLayers(); 943 frame_provider_ = NULL; 944 layer_ = NULL; 945 // This gets called when ever any eviction, loosing resources, swapping 946 // problems are encountered and so we abort any pending readbacks here. 947 AbortPendingReadbackRequests(); 948 } 949 950 void RenderWidgetHostViewAndroid::SwapDelegatedFrame( 951 uint32 output_surface_id, 952 scoped_ptr<cc::DelegatedFrameData> frame_data) { 953 bool has_content = !texture_size_in_layer_.IsEmpty(); 954 955 if (output_surface_id != last_output_surface_id_) { 956 // Drop the cc::DelegatedFrameResourceCollection so that we will not return 957 // any resources from the old output surface with the new output surface id. 958 if (resource_collection_.get()) { 959 resource_collection_->SetClient(NULL); 960 if (resource_collection_->LoseAllResources()) 961 SendReturnedDelegatedResources(last_output_surface_id_); 962 resource_collection_ = NULL; 963 } 964 DestroyDelegatedContent(); 965 966 last_output_surface_id_ = output_surface_id; 967 } 968 969 // DelegatedRendererLayerImpl applies the inverse device_scale_factor of the 970 // renderer frame, assuming that the browser compositor will scale 971 // it back up to device scale. But on Android we put our browser layers in 972 // physical pixels and set our browser CC device_scale_factor to 1, so this 973 // suppresses the transform. This line may need to be removed when fixing 974 // http://crbug.com/384134 or http://crbug.com/310763 975 frame_data->device_scale_factor = 1.0f; 976 977 if (!has_content) { 978 DestroyDelegatedContent(); 979 } else { 980 if (!resource_collection_.get()) { 981 resource_collection_ = new cc::DelegatedFrameResourceCollection; 982 resource_collection_->SetClient(this); 983 } 984 if (!frame_provider_ || 985 texture_size_in_layer_ != frame_provider_->frame_size()) { 986 RemoveLayers(); 987 frame_provider_ = new cc::DelegatedFrameProvider( 988 resource_collection_.get(), frame_data.Pass()); 989 layer_ = cc::DelegatedRendererLayer::Create(frame_provider_); 990 AttachLayers(); 991 } else { 992 frame_provider_->SetFrameData(frame_data.Pass()); 993 } 994 } 995 996 if (layer_.get()) { 997 layer_->SetIsDrawable(true); 998 layer_->SetContentsOpaque(true); 999 layer_->SetBounds(content_size_in_layer_); 1000 layer_->SetNeedsDisplay(); 1001 } 1002 1003 base::Closure ack_callback = 1004 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck, 1005 weak_ptr_factory_.GetWeakPtr(), 1006 output_surface_id); 1007 1008 ack_callbacks_.push(ack_callback); 1009 if (host_->is_hidden()) 1010 RunAckCallbacks(); 1011 } 1012 1013 void RenderWidgetHostViewAndroid::ComputeContentsSize( 1014 const cc::CompositorFrameMetadata& frame_metadata) { 1015 // Calculate the content size. This should be 0 if the texture_size is 0. 1016 gfx::Vector2dF offset; 1017 if (texture_size_in_layer_.IsEmpty()) 1018 content_size_in_layer_ = gfx::Size(); 1019 content_size_in_layer_ = gfx::ToCeiledSize(gfx::ScaleSize( 1020 frame_metadata.scrollable_viewport_size, 1021 frame_metadata.device_scale_factor * frame_metadata.page_scale_factor)); 1022 1023 if (overscroll_effect_) { 1024 overscroll_effect_->UpdateDisplayParameters( 1025 CreateOverscrollDisplayParameters(frame_metadata)); 1026 } 1027 } 1028 1029 void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame( 1030 uint32 output_surface_id, 1031 scoped_ptr<cc::CompositorFrame> frame) { 1032 last_scroll_offset_ = frame->metadata.root_scroll_offset; 1033 if (!frame->delegated_frame_data) { 1034 LOG(ERROR) << "Non-delegated renderer path no longer supported"; 1035 return; 1036 } 1037 1038 if (locks_on_frame_count_ > 0) { 1039 DCHECK(HasValidFrame()); 1040 RetainFrame(output_surface_id, frame.Pass()); 1041 return; 1042 } 1043 1044 if (layer_ && layer_->layer_tree_host()) { 1045 for (size_t i = 0; i < frame->metadata.latency_info.size(); i++) { 1046 scoped_ptr<cc::SwapPromise> swap_promise( 1047 new cc::LatencyInfoSwapPromise(frame->metadata.latency_info[i])); 1048 layer_->layer_tree_host()->QueueSwapPromise(swap_promise.Pass()); 1049 } 1050 } 1051 1052 DCHECK(!frame->delegated_frame_data->render_pass_list.empty()); 1053 1054 cc::RenderPass* root_pass = 1055 frame->delegated_frame_data->render_pass_list.back(); 1056 texture_size_in_layer_ = root_pass->output_rect.size(); 1057 ComputeContentsSize(frame->metadata); 1058 1059 SwapDelegatedFrame(output_surface_id, frame->delegated_frame_data.Pass()); 1060 frame_evictor_->SwappedFrame(!host_->is_hidden()); 1061 1062 // As the metadata update may trigger view invalidation, always call it after 1063 // any potential compositor scheduling. 1064 OnFrameMetadataUpdated(frame->metadata); 1065 // Check if we have any pending readbacks, see if we have a frame available 1066 // and process them here. 1067 if (!readbacks_waiting_for_frame_.empty()) { 1068 while (!readbacks_waiting_for_frame_.empty()) { 1069 ReadbackRequest& readback_request = readbacks_waiting_for_frame_.front(); 1070 GetScaledContentBitmap(readback_request.GetScale(), 1071 readback_request.GetColorFormat(), 1072 readback_request.GetCaptureRect(), 1073 readback_request.GetResultCallback()); 1074 readbacks_waiting_for_frame_.pop(); 1075 } 1076 } 1077 } 1078 1079 void RenderWidgetHostViewAndroid::OnSwapCompositorFrame( 1080 uint32 output_surface_id, 1081 scoped_ptr<cc::CompositorFrame> frame) { 1082 InternalSwapCompositorFrame(output_surface_id, frame.Pass()); 1083 } 1084 1085 void RenderWidgetHostViewAndroid::RetainFrame( 1086 uint32 output_surface_id, 1087 scoped_ptr<cc::CompositorFrame> frame) { 1088 DCHECK(locks_on_frame_count_); 1089 1090 // Store the incoming frame so that it can be swapped when all the locks have 1091 // been released. If there is already a stored frame, then replace and skip 1092 // the previous one but make sure we still eventually send the ACK. Holding 1093 // the ACK also blocks the renderer when its max_frames_pending is reached. 1094 if (last_frame_info_) { 1095 base::Closure ack_callback = 1096 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck, 1097 weak_ptr_factory_.GetWeakPtr(), 1098 last_frame_info_->output_surface_id); 1099 1100 ack_callbacks_.push(ack_callback); 1101 } 1102 1103 last_frame_info_.reset(new LastFrameInfo(output_surface_id, frame.Pass())); 1104 } 1105 1106 void RenderWidgetHostViewAndroid::SynchronousFrameMetadata( 1107 const cc::CompositorFrameMetadata& frame_metadata) { 1108 if (!content_view_core_) 1109 return; 1110 1111 // This is a subset of OnSwapCompositorFrame() used in the synchronous 1112 // compositor flow. 1113 OnFrameMetadataUpdated(frame_metadata); 1114 ComputeContentsSize(frame_metadata); 1115 1116 // DevTools ScreenCast support for Android WebView. 1117 WebContents* web_contents = content_view_core_->GetWebContents(); 1118 if (DevToolsAgentHost::HasFor(web_contents)) { 1119 scoped_refptr<DevToolsAgentHost> dtah = 1120 DevToolsAgentHost::GetOrCreateFor(web_contents); 1121 // Unblock the compositor. 1122 BrowserThread::PostTask( 1123 BrowserThread::UI, FROM_HERE, 1124 base::Bind(&RenderViewDevToolsAgentHost::SynchronousSwapCompositorFrame, 1125 static_cast<RenderViewDevToolsAgentHost*>(dtah.get()), 1126 frame_metadata)); 1127 } 1128 } 1129 1130 void RenderWidgetHostViewAndroid::SetOverlayVideoMode(bool enabled) { 1131 if (layer_) 1132 layer_->SetContentsOpaque(!enabled); 1133 } 1134 1135 bool RenderWidgetHostViewAndroid::SupportsAnimation() const { 1136 // The synchronous (WebView) compositor does not have a proper browser 1137 // compositor with which to drive animations. 1138 return using_browser_compositor_; 1139 } 1140 1141 void RenderWidgetHostViewAndroid::SetNeedsAnimate() { 1142 DCHECK(content_view_core_); 1143 DCHECK(using_browser_compositor_); 1144 content_view_core_->GetWindowAndroid()->SetNeedsAnimate(); 1145 } 1146 1147 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::PointF& position) { 1148 MoveCaret(gfx::Point(position.x(), position.y())); 1149 } 1150 1151 void RenderWidgetHostViewAndroid::SelectBetweenCoordinates( 1152 const gfx::PointF& start, 1153 const gfx::PointF& end) { 1154 DCHECK(content_view_core_); 1155 content_view_core_->SelectBetweenCoordinates(start, end); 1156 } 1157 1158 void RenderWidgetHostViewAndroid::OnSelectionEvent( 1159 SelectionEventType event, 1160 const gfx::PointF& position) { 1161 DCHECK(content_view_core_); 1162 content_view_core_->OnSelectionEvent(event, position); 1163 } 1164 1165 scoped_ptr<TouchHandleDrawable> RenderWidgetHostViewAndroid::CreateDrawable() { 1166 DCHECK(content_view_core_); 1167 if (!using_browser_compositor_) 1168 return content_view_core_->CreatePopupTouchHandleDrawable(); 1169 1170 return scoped_ptr<TouchHandleDrawable>(new CompositedTouchHandleDrawable( 1171 content_view_core_->GetLayer(), 1172 content_view_core_->GetDpiScale(), 1173 base::android::GetApplicationContext())); 1174 } 1175 1176 void RenderWidgetHostViewAndroid::SynchronousCopyContents( 1177 const gfx::Rect& src_subrect_in_pixel, 1178 const gfx::Size& dst_size_in_pixel, 1179 const base::Callback<void(bool, const SkBitmap&)>& callback, 1180 const SkColorType color_type) { 1181 SynchronousCompositor* compositor = 1182 SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(), 1183 host_->GetRoutingID()); 1184 if (!compositor) { 1185 callback.Run(false, SkBitmap()); 1186 return; 1187 } 1188 1189 SkBitmap bitmap; 1190 bitmap.allocPixels(SkImageInfo::Make(dst_size_in_pixel.width(), 1191 dst_size_in_pixel.height(), 1192 color_type, 1193 kPremul_SkAlphaType)); 1194 SkCanvas canvas(bitmap); 1195 canvas.scale( 1196 (float)dst_size_in_pixel.width() / (float)src_subrect_in_pixel.width(), 1197 (float)dst_size_in_pixel.height() / (float)src_subrect_in_pixel.height()); 1198 compositor->DemandDrawSw(&canvas); 1199 callback.Run(true, bitmap); 1200 } 1201 1202 void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated( 1203 const cc::CompositorFrameMetadata& frame_metadata) { 1204 1205 // Disable double tap zoom for pages that have a width=device-width or 1206 // narrower viewport (indicating that this is a mobile-optimized or responsive 1207 // web design, so text will be legible without zooming). Also disable 1208 // double tap and pinch for pages that prevent zooming in or out. 1209 bool has_mobile_viewport = HasMobileViewport(frame_metadata); 1210 bool has_fixed_page_scale = HasFixedPageScale(frame_metadata); 1211 gesture_provider_.SetDoubleTapSupportForPageEnabled( 1212 !has_fixed_page_scale && !has_mobile_viewport); 1213 1214 if (!content_view_core_) 1215 return; 1216 1217 if (selection_controller_) { 1218 selection_controller_->OnSelectionBoundsChanged( 1219 frame_metadata.selection_start, frame_metadata.selection_end); 1220 } 1221 1222 // All offsets and sizes are in CSS pixels. 1223 content_view_core_->UpdateFrameInfo( 1224 frame_metadata.root_scroll_offset, 1225 frame_metadata.page_scale_factor, 1226 gfx::Vector2dF(frame_metadata.min_page_scale_factor, 1227 frame_metadata.max_page_scale_factor), 1228 frame_metadata.root_layer_size, 1229 frame_metadata.scrollable_viewport_size, 1230 frame_metadata.location_bar_offset, 1231 frame_metadata.location_bar_content_translation); 1232 #if defined(VIDEO_HOLE) 1233 if (host_ && host_->IsRenderView()) { 1234 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>( 1235 RenderViewHost::From(host_)); 1236 rvhi->media_web_contents_observer()->OnFrameInfoUpdated(); 1237 } 1238 #endif // defined(VIDEO_HOLE) 1239 } 1240 1241 void RenderWidgetHostViewAndroid::AcceleratedSurfaceInitialized(int host_id, 1242 int route_id) { 1243 accelerated_surface_route_id_ = route_id; 1244 } 1245 1246 void RenderWidgetHostViewAndroid::AcceleratedSurfaceBuffersSwapped( 1247 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params, 1248 int gpu_host_id) { 1249 NOTREACHED() << "Need --composite-to-mailbox or --enable-delegated-renderer"; 1250 } 1251 1252 void RenderWidgetHostViewAndroid::AttachLayers() { 1253 if (!content_view_core_) 1254 return; 1255 if (!layer_.get()) 1256 return; 1257 1258 content_view_core_->AttachLayer(layer_); 1259 if (overscroll_effect_) 1260 overscroll_effect_->Enable(); 1261 layer_->SetHideLayerAndSubtree(!is_showing_); 1262 } 1263 1264 void RenderWidgetHostViewAndroid::RemoveLayers() { 1265 if (!content_view_core_) 1266 return; 1267 1268 if (!layer_.get()) 1269 return; 1270 1271 content_view_core_->RemoveLayer(layer_); 1272 if (overscroll_effect_) 1273 overscroll_effect_->Disable(); 1274 } 1275 1276 void RenderWidgetHostViewAndroid::RequestVSyncUpdate(uint32 requests) { 1277 // The synchronous compositor does not requre BeginFrame messages. 1278 if (!using_browser_compositor_) 1279 requests &= FLUSH_INPUT; 1280 1281 bool should_request_vsync = !outstanding_vsync_requests_ && requests; 1282 outstanding_vsync_requests_ |= requests; 1283 // Note that if we're not currently observing the root window, outstanding 1284 // vsync requests will be pushed if/when we resume observing in 1285 // |StartObservingRootWindow()|. 1286 if (observing_root_window_ && should_request_vsync) 1287 content_view_core_->GetWindowAndroid()->RequestVSyncUpdate(); 1288 } 1289 1290 void RenderWidgetHostViewAndroid::StartObservingRootWindow() { 1291 DCHECK(content_view_core_); 1292 if (observing_root_window_) 1293 return; 1294 1295 observing_root_window_ = true; 1296 content_view_core_->GetWindowAndroid()->AddObserver(this); 1297 1298 // Clear existing vsync requests to allow a request to the new window. 1299 uint32 outstanding_vsync_requests = outstanding_vsync_requests_; 1300 outstanding_vsync_requests_ = 0; 1301 RequestVSyncUpdate(outstanding_vsync_requests); 1302 } 1303 1304 void RenderWidgetHostViewAndroid::StopObservingRootWindow() { 1305 if (!content_view_core_) { 1306 DCHECK(!observing_root_window_); 1307 return; 1308 } 1309 1310 if (!observing_root_window_) 1311 return; 1312 1313 observing_root_window_ = false; 1314 content_view_core_->GetWindowAndroid()->RemoveObserver(this); 1315 } 1316 1317 void RenderWidgetHostViewAndroid::SendBeginFrame(base::TimeTicks frame_time, 1318 base::TimeDelta vsync_period) { 1319 TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::SendBeginFrame", 1320 "frame_time_us", frame_time.ToInternalValue()); 1321 base::TimeTicks display_time = frame_time + vsync_period; 1322 1323 // TODO(brianderson): Use adaptive draw-time estimation. 1324 base::TimeDelta estimated_browser_composite_time = 1325 base::TimeDelta::FromMicroseconds( 1326 (1.0f * base::Time::kMicrosecondsPerSecond) / (3.0f * 60)); 1327 1328 base::TimeTicks deadline = display_time - estimated_browser_composite_time; 1329 1330 host_->Send(new ViewMsg_BeginFrame( 1331 host_->GetRoutingID(), 1332 cc::BeginFrameArgs::Create(frame_time, deadline, vsync_period))); 1333 } 1334 1335 bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) { 1336 bool needs_animate = 1337 overscroll_effect_ ? overscroll_effect_->Animate(frame_time) : false; 1338 if (selection_controller_) 1339 needs_animate |= selection_controller_->Animate(frame_time); 1340 return needs_animate; 1341 } 1342 1343 void RenderWidgetHostViewAndroid::AcceleratedSurfacePostSubBuffer( 1344 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params, 1345 int gpu_host_id) { 1346 NOTREACHED(); 1347 } 1348 1349 void RenderWidgetHostViewAndroid::AcceleratedSurfaceSuspend() { 1350 NOTREACHED(); 1351 } 1352 1353 void RenderWidgetHostViewAndroid::AcceleratedSurfaceRelease() { 1354 NOTREACHED(); 1355 } 1356 1357 void RenderWidgetHostViewAndroid::EvictDelegatedFrame() { 1358 if (layer_.get()) 1359 DestroyDelegatedContent(); 1360 frame_evictor_->DiscardedFrame(); 1361 // We are evicting the delegated frame, 1362 // so there should be no pending readback requests 1363 DCHECK(readbacks_waiting_for_frame_.empty()); 1364 } 1365 1366 bool RenderWidgetHostViewAndroid::HasAcceleratedSurface( 1367 const gfx::Size& desired_size) { 1368 NOTREACHED(); 1369 return false; 1370 } 1371 1372 void RenderWidgetHostViewAndroid::GetScreenInfo(blink::WebScreenInfo* result) { 1373 // ScreenInfo isn't tied to the widget on Android. Always return the default. 1374 RenderWidgetHostViewBase::GetDefaultScreenInfo(result); 1375 } 1376 1377 // TODO(jrg): Find out the implications and answer correctly here, 1378 // as we are returning the WebView and not root window bounds. 1379 gfx::Rect RenderWidgetHostViewAndroid::GetBoundsInRootWindow() { 1380 return GetViewBounds(); 1381 } 1382 1383 gfx::GLSurfaceHandle RenderWidgetHostViewAndroid::GetCompositingSurface() { 1384 gfx::GLSurfaceHandle handle = 1385 gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NATIVE_TRANSPORT); 1386 if (using_browser_compositor_) { 1387 handle.parent_client_id = 1388 ImageTransportFactoryAndroid::GetInstance()->GetChannelID(); 1389 } 1390 return handle; 1391 } 1392 1393 void RenderWidgetHostViewAndroid::ProcessAckedTouchEvent( 1394 const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) { 1395 const bool event_consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED; 1396 gesture_provider_.OnTouchEventAck(event_consumed); 1397 } 1398 1399 void RenderWidgetHostViewAndroid::GestureEventAck( 1400 const blink::WebGestureEvent& event, 1401 InputEventAckState ack_result) { 1402 // The overscroll effect requires an explicit release signal that may not be 1403 // sent from the renderer compositor. 1404 if (event.type == blink::WebInputEvent::GestureScrollEnd || 1405 event.type == blink::WebInputEvent::GestureFlingStart) { 1406 DidOverscroll(DidOverscrollParams()); 1407 } 1408 1409 if (content_view_core_) 1410 content_view_core_->OnGestureEventAck(event, ack_result); 1411 } 1412 1413 InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent( 1414 const blink::WebInputEvent& input_event) { 1415 if (selection_controller_) { 1416 switch (input_event.type) { 1417 case blink::WebInputEvent::GestureLongPress: 1418 selection_controller_->OnLongPressEvent(); 1419 break; 1420 case blink::WebInputEvent::GestureTap: 1421 selection_controller_->OnTapEvent(); 1422 break; 1423 default: 1424 break; 1425 } 1426 } 1427 1428 if (content_view_core_ && 1429 content_view_core_->FilterInputEvent(input_event)) 1430 return INPUT_EVENT_ACK_STATE_CONSUMED; 1431 1432 if (!host_) 1433 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED; 1434 1435 if (input_event.type == blink::WebInputEvent::GestureTapDown || 1436 input_event.type == blink::WebInputEvent::TouchStart) { 1437 GpuDataManagerImpl* gpu_data = GpuDataManagerImpl::GetInstance(); 1438 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance(); 1439 if (shim && gpu_data && accelerated_surface_route_id_ && 1440 gpu_data->IsDriverBugWorkaroundActive(gpu::WAKE_UP_GPU_BEFORE_DRAWING)) 1441 shim->Send( 1442 new AcceleratedSurfaceMsg_WakeUpGpu(accelerated_surface_route_id_)); 1443 } 1444 1445 SynchronousCompositorImpl* compositor = 1446 SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(), 1447 host_->GetRoutingID()); 1448 if (compositor) 1449 return compositor->HandleInputEvent(input_event); 1450 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED; 1451 } 1452 1453 void RenderWidgetHostViewAndroid::OnSetNeedsFlushInput() { 1454 TRACE_EVENT0("input", "RenderWidgetHostViewAndroid::OnSetNeedsFlushInput"); 1455 RequestVSyncUpdate(FLUSH_INPUT); 1456 } 1457 1458 BrowserAccessibilityManager* 1459 RenderWidgetHostViewAndroid::CreateBrowserAccessibilityManager( 1460 BrowserAccessibilityDelegate* delegate) { 1461 // TODO(dmazzoni): Currently there can only be one 1462 // BrowserAccessibilityManager per ContentViewCore, so return NULL 1463 // if there's already a BrowserAccessibilityManager for the main 1464 // frame. Eventually, in order to support cross-process iframes on 1465 // Android we'll need to add support for a 1466 // BrowserAccessibilityManager for a child frame. 1467 // http://crbug.com/423846 1468 if (!host_ || host_->GetRootBrowserAccessibilityManager()) 1469 return NULL; 1470 1471 base::android::ScopedJavaLocalRef<jobject> obj; 1472 if (content_view_core_) 1473 obj = content_view_core_->GetJavaObject(); 1474 return new BrowserAccessibilityManagerAndroid( 1475 obj, 1476 BrowserAccessibilityManagerAndroid::GetEmptyDocument(), 1477 delegate); 1478 } 1479 1480 bool RenderWidgetHostViewAndroid::LockMouse() { 1481 NOTIMPLEMENTED(); 1482 return false; 1483 } 1484 1485 void RenderWidgetHostViewAndroid::UnlockMouse() { 1486 NOTIMPLEMENTED(); 1487 } 1488 1489 // Methods called from the host to the render 1490 1491 void RenderWidgetHostViewAndroid::SendKeyEvent( 1492 const NativeWebKeyboardEvent& event) { 1493 if (host_) 1494 host_->ForwardKeyboardEvent(event); 1495 } 1496 1497 void RenderWidgetHostViewAndroid::SendMouseEvent( 1498 const blink::WebMouseEvent& event) { 1499 if (host_) 1500 host_->ForwardMouseEvent(event); 1501 } 1502 1503 void RenderWidgetHostViewAndroid::SendMouseWheelEvent( 1504 const blink::WebMouseWheelEvent& event) { 1505 if (host_) 1506 host_->ForwardWheelEvent(event); 1507 } 1508 1509 void RenderWidgetHostViewAndroid::SendGestureEvent( 1510 const blink::WebGestureEvent& event) { 1511 // Sending a gesture that may trigger overscroll should resume the effect. 1512 if (overscroll_effect_) 1513 overscroll_effect_->Enable(); 1514 1515 if (host_) 1516 host_->ForwardGestureEventWithLatencyInfo(event, CreateLatencyInfo(event)); 1517 } 1518 1519 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point& point) { 1520 if (host_) 1521 host_->MoveCaret(point); 1522 } 1523 1524 void RenderWidgetHostViewAndroid::DismissTextHandles() { 1525 if (selection_controller_) 1526 selection_controller_->HideAndDisallowShowingAutomatically(); 1527 } 1528 1529 void RenderWidgetHostViewAndroid::SetTextHandlesTemporarilyHidden(bool hidden) { 1530 if (selection_controller_) 1531 selection_controller_->SetTemporarilyHidden(hidden); 1532 } 1533 1534 void RenderWidgetHostViewAndroid::OnShowingPastePopup( 1535 const gfx::PointF& point) { 1536 if (!selection_controller_) 1537 return; 1538 1539 // As the paste popup may be triggered *before* the bounds and editability 1540 // of the region have been updated, explicitly set the properties now. 1541 // TODO(jdduke): Remove this workaround when auxiliary paste popup 1542 // notifications are no longer required, crbug.com/398170. 1543 cc::ViewportSelectionBound insertion_bound; 1544 insertion_bound.type = cc::SELECTION_BOUND_CENTER; 1545 insertion_bound.visible = true; 1546 insertion_bound.edge_top = point; 1547 insertion_bound.edge_bottom = point; 1548 DismissTextHandles(); 1549 ShowSelectionHandlesAutomatically(); 1550 selection_controller_->OnSelectionEditable(true); 1551 selection_controller_->OnSelectionEmpty(true); 1552 selection_controller_->OnSelectionBoundsChanged(insertion_bound, 1553 insertion_bound); 1554 } 1555 1556 SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const { 1557 return cached_background_color_; 1558 } 1559 1560 void RenderWidgetHostViewAndroid::DidOverscroll( 1561 const DidOverscrollParams& params) { 1562 if (!content_view_core_ || !layer_ || !is_showing_) 1563 return; 1564 1565 const float device_scale_factor = content_view_core_->GetDpiScale(); 1566 1567 if (overscroll_effect_ && 1568 overscroll_effect_->OnOverscrolled( 1569 content_view_core_->GetLayer(), 1570 base::TimeTicks::Now(), 1571 gfx::ScaleVector2d(params.accumulated_overscroll, 1572 device_scale_factor), 1573 gfx::ScaleVector2d(params.latest_overscroll_delta, 1574 device_scale_factor), 1575 gfx::ScaleVector2d(params.current_fling_velocity, 1576 device_scale_factor), 1577 gfx::ScaleVector2d( 1578 params.causal_event_viewport_point.OffsetFromOrigin(), 1579 device_scale_factor))) { 1580 SetNeedsAnimate(); 1581 } 1582 } 1583 1584 void RenderWidgetHostViewAndroid::DidStopFlinging() { 1585 if (content_view_core_) 1586 content_view_core_->DidStopFlinging(); 1587 } 1588 1589 void RenderWidgetHostViewAndroid::SetContentViewCore( 1590 ContentViewCoreImpl* content_view_core) { 1591 RemoveLayers(); 1592 StopObservingRootWindow(); 1593 1594 bool resize = false; 1595 if (content_view_core != content_view_core_) { 1596 overscroll_effect_.reset(); 1597 selection_controller_.reset(); 1598 ReleaseLocksOnSurface(); 1599 resize = true; 1600 } 1601 1602 content_view_core_ = content_view_core; 1603 1604 BrowserAccessibilityManager* manager = NULL; 1605 if (host_) 1606 manager = host_->GetRootBrowserAccessibilityManager(); 1607 if (manager) { 1608 base::android::ScopedJavaLocalRef<jobject> obj; 1609 if (content_view_core_) 1610 obj = content_view_core_->GetJavaObject(); 1611 manager->ToBrowserAccessibilityManagerAndroid()->SetContentViewCore(obj); 1612 } 1613 1614 AttachLayers(); 1615 1616 if (!content_view_core_) 1617 return; 1618 1619 StartObservingRootWindow(); 1620 1621 if (resize) 1622 WasResized(); 1623 1624 if (!selection_controller_) 1625 selection_controller_ = CreateSelectionController(this, content_view_core_); 1626 1627 if (overscroll_effect_enabled_ && !overscroll_effect_ && 1628 content_view_core_->GetWindowAndroid()->GetCompositor()) 1629 overscroll_effect_ = CreateOverscrollEffect(content_view_core_); 1630 } 1631 1632 void RenderWidgetHostViewAndroid::RunAckCallbacks() { 1633 while (!ack_callbacks_.empty()) { 1634 ack_callbacks_.front().Run(); 1635 ack_callbacks_.pop(); 1636 } 1637 } 1638 1639 void RenderWidgetHostViewAndroid::OnGestureEvent( 1640 const ui::GestureEventData& gesture) { 1641 if (gesture_text_selector_.OnGestureEvent(gesture)) 1642 return; 1643 1644 SendGestureEvent(CreateWebGestureEventFromGestureEventData(gesture)); 1645 } 1646 1647 void RenderWidgetHostViewAndroid::OnCompositingDidCommit() { 1648 RunAckCallbacks(); 1649 } 1650 1651 1652 void RenderWidgetHostViewAndroid::OnAttachCompositor() { 1653 DCHECK(content_view_core_); 1654 if (overscroll_effect_enabled_ && !overscroll_effect_) 1655 overscroll_effect_ = CreateOverscrollEffect(content_view_core_); 1656 } 1657 1658 void RenderWidgetHostViewAndroid::OnDetachCompositor() { 1659 DCHECK(content_view_core_); 1660 DCHECK(using_browser_compositor_); 1661 RunAckCallbacks(); 1662 overscroll_effect_.reset(); 1663 } 1664 1665 void RenderWidgetHostViewAndroid::OnVSync(base::TimeTicks frame_time, 1666 base::TimeDelta vsync_period) { 1667 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::OnVSync"); 1668 if (!host_) 1669 return; 1670 1671 const uint32 current_vsync_requests = outstanding_vsync_requests_; 1672 outstanding_vsync_requests_ = 0; 1673 1674 if (current_vsync_requests & FLUSH_INPUT) 1675 host_->FlushInput(); 1676 1677 if (current_vsync_requests & BEGIN_FRAME || 1678 current_vsync_requests & PERSISTENT_BEGIN_FRAME) { 1679 SendBeginFrame(frame_time, vsync_period); 1680 } 1681 1682 if (current_vsync_requests & PERSISTENT_BEGIN_FRAME) 1683 RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME); 1684 } 1685 1686 void RenderWidgetHostViewAndroid::OnAnimate(base::TimeTicks begin_frame_time) { 1687 if (Animate(begin_frame_time)) 1688 SetNeedsAnimate(); 1689 } 1690 1691 void RenderWidgetHostViewAndroid::OnLostResources() { 1692 ReleaseLocksOnSurface(); 1693 if (layer_.get()) 1694 DestroyDelegatedContent(); 1695 DCHECK(ack_callbacks_.empty()); 1696 // We should not loose a frame if we have readback requests pending. 1697 DCHECK(readbacks_waiting_for_frame_.empty()); 1698 } 1699 1700 // static 1701 void 1702 RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResultForDelegatedReadback( 1703 const gfx::Size& dst_size_in_pixel, 1704 const SkColorType color_type, 1705 const base::TimeTicks& start_time, 1706 scoped_refptr<cc::Layer> readback_layer, 1707 const base::Callback<void(bool, const SkBitmap&)>& callback, 1708 scoped_ptr<cc::CopyOutputResult> result) { 1709 readback_layer->RemoveFromParent(); 1710 PrepareTextureCopyOutputResult( 1711 dst_size_in_pixel, color_type, start_time, callback, result.Pass()); 1712 } 1713 1714 // static 1715 void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult( 1716 const gfx::Size& dst_size_in_pixel, 1717 const SkColorType color_type, 1718 const base::TimeTicks& start_time, 1719 const base::Callback<void(bool, const SkBitmap&)>& callback, 1720 scoped_ptr<cc::CopyOutputResult> result) { 1721 base::ScopedClosureRunner scoped_callback_runner( 1722 base::Bind(callback, false, SkBitmap())); 1723 TRACE_EVENT0("cc", 1724 "RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult"); 1725 1726 if (!result->HasTexture() || result->IsEmpty() || result->size().IsEmpty()) 1727 return; 1728 1729 scoped_ptr<SkBitmap> bitmap(new SkBitmap); 1730 if (!bitmap->tryAllocPixels(SkImageInfo::Make(dst_size_in_pixel.width(), 1731 dst_size_in_pixel.height(), 1732 color_type, 1733 kOpaque_SkAlphaType))) 1734 return; 1735 1736 ImageTransportFactoryAndroid* factory = 1737 ImageTransportFactoryAndroid::GetInstance(); 1738 GLHelper* gl_helper = factory->GetGLHelper(); 1739 1740 if (!gl_helper) 1741 return; 1742 1743 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock( 1744 new SkAutoLockPixels(*bitmap)); 1745 uint8* pixels = static_cast<uint8*>(bitmap->getPixels()); 1746 1747 cc::TextureMailbox texture_mailbox; 1748 scoped_ptr<cc::SingleReleaseCallback> release_callback; 1749 result->TakeTexture(&texture_mailbox, &release_callback); 1750 DCHECK(texture_mailbox.IsTexture()); 1751 if (!texture_mailbox.IsTexture()) 1752 return; 1753 1754 ignore_result(scoped_callback_runner.Release()); 1755 1756 gl_helper->CropScaleReadbackAndCleanMailbox( 1757 texture_mailbox.mailbox(), 1758 texture_mailbox.sync_point(), 1759 result->size(), 1760 gfx::Rect(result->size()), 1761 dst_size_in_pixel, 1762 pixels, 1763 color_type, 1764 base::Bind(&CopyFromCompositingSurfaceFinished, 1765 callback, 1766 base::Passed(&release_callback), 1767 base::Passed(&bitmap), 1768 start_time, 1769 base::Passed(&bitmap_pixels_lock)), 1770 GLHelper::SCALER_QUALITY_GOOD); 1771 } 1772 1773 bool RenderWidgetHostViewAndroid::IsReadbackConfigSupported( 1774 SkColorType color_type) { 1775 ImageTransportFactoryAndroid* factory = 1776 ImageTransportFactoryAndroid::GetInstance(); 1777 GLHelper* gl_helper = factory->GetGLHelper(); 1778 if (!gl_helper) 1779 return false; 1780 return gl_helper->IsReadbackConfigSupported(color_type); 1781 } 1782 1783 SkColorType RenderWidgetHostViewAndroid::PreferredReadbackFormat() { 1784 // Define the criteria here. If say the 16 texture readback is 1785 // supported we should go with that (this degrades quality) 1786 // or stick back to the default format. 1787 if (base::SysInfo::IsLowEndDevice()) { 1788 if (IsReadbackConfigSupported(kRGB_565_SkColorType)) 1789 return kRGB_565_SkColorType; 1790 } 1791 return kN32_SkColorType; 1792 } 1793 1794 void RenderWidgetHostViewAndroid::ShowSelectionHandlesAutomatically() { 1795 // Fake a long press to allow automatic selection handle showing. 1796 if (selection_controller_) 1797 selection_controller_->OnLongPressEvent(); 1798 } 1799 1800 void RenderWidgetHostViewAndroid::SelectRange( 1801 float x1, float y1, float x2, float y2) { 1802 if (content_view_core_) 1803 static_cast<WebContentsImpl*>(content_view_core_->GetWebContents())-> 1804 SelectRange(gfx::Point(x1, y1), gfx::Point(x2, y2)); 1805 } 1806 1807 void RenderWidgetHostViewAndroid::Unselect() { 1808 if (content_view_core_) 1809 content_view_core_->GetWebContents()->Unselect(); 1810 } 1811 1812 void RenderWidgetHostViewAndroid::LongPress( 1813 base::TimeTicks time, float x, float y) { 1814 blink::WebGestureEvent long_press = WebGestureEventBuilder::Build( 1815 blink::WebInputEvent::GestureLongPress, 1816 (time - base::TimeTicks()).InSecondsF(), x, y); 1817 SendGestureEvent(long_press); 1818 } 1819 1820 // static 1821 void RenderWidgetHostViewBase::GetDefaultScreenInfo( 1822 blink::WebScreenInfo* results) { 1823 const gfx::Display& display = 1824 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay(); 1825 results->rect = display.bounds(); 1826 // TODO(husky): Remove any system controls from availableRect. 1827 results->availableRect = display.work_area(); 1828 results->deviceScaleFactor = display.device_scale_factor(); 1829 results->orientationAngle = display.RotationAsDegree(); 1830 results->orientationType = 1831 RenderWidgetHostViewBase::GetOrientationTypeForMobile(display); 1832 gfx::DeviceDisplayInfo info; 1833 results->depth = info.GetBitsPerPixel(); 1834 results->depthPerComponent = info.GetBitsPerComponent(); 1835 results->isMonochrome = (results->depthPerComponent == 0); 1836 } 1837 1838 } // namespace content 1839