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 "base/bind_helpers.h"
6 #include "base/command_line.h"
7 #include "base/logging.h"
8 #include "base/message_loop.h"
9 #include "content/browser/browser_plugin/browser_plugin_guest.h"
10 #include "content/browser/renderer_host/render_view_host_impl.h"
11 #include "content/browser/renderer_host/render_widget_host_view_guest.h"
12 #if defined(OS_WIN) || defined(USE_AURA)
13 #include "content/browser/renderer_host/ui_events_helper.h"
15 #include "content/common/browser_plugin/browser_plugin_messages.h"
16 #include "content/common/gpu/gpu_messages.h"
17 #include "content/common/view_messages.h"
18 #include "content/public/common/content_switches.h"
19 #include "skia/ext/platform_canvas.h"
20 #include "third_party/WebKit/public/web/WebScreenInfo.h"
21 #include "webkit/plugins/npapi/webplugin.h"
27 bool ShouldSendPinchGesture() {
28 static bool pinch_allowed
=
29 CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnablePinch
);
33 WebKit::WebGestureEvent
CreateFlingCancelEvent(double time_stamp
) {
34 WebKit::WebGestureEvent gesture_event
;
35 gesture_event
.timeStampSeconds
= time_stamp
;
36 gesture_event
.type
= WebKit::WebGestureEvent::GestureFlingCancel
;
37 gesture_event
.sourceDevice
= WebKit::WebGestureEvent::Touchscreen
;
43 RenderWidgetHostViewGuest::RenderWidgetHostViewGuest(
44 RenderWidgetHost
* widget_host
,
45 BrowserPluginGuest
* guest
,
46 RenderWidgetHostView
* platform_view
)
47 : host_(RenderWidgetHostImpl::From(widget_host
)),
50 platform_view_(static_cast<RenderWidgetHostViewPort
*>(platform_view
)) {
51 #if defined(OS_WIN) || defined(USE_AURA)
52 gesture_recognizer_
.reset(ui::GestureRecognizer::Create(this));
53 #endif // defined(OS_WIN) || defined(USE_AURA)
57 RenderWidgetHostViewGuest::~RenderWidgetHostViewGuest() {
60 RenderWidgetHost
* RenderWidgetHostViewGuest::GetRenderWidgetHost() const {
64 void RenderWidgetHostViewGuest::WasShown() {
71 void RenderWidgetHostViewGuest::WasHidden() {
78 void RenderWidgetHostViewGuest::SetSize(const gfx::Size
& size
) {
83 gfx::Rect
RenderWidgetHostViewGuest::GetBoundsInRootWindow() {
84 // We do not have any root window specific parts in this view.
85 return GetViewBounds();
88 gfx::GLSurfaceHandle
RenderWidgetHostViewGuest::GetCompositingSurface() {
89 return gfx::GLSurfaceHandle(gfx::kNullPluginWindow
, gfx::TEXTURE_TRANSPORT
);
92 #if defined(OS_WIN) || defined(USE_AURA)
93 void RenderWidgetHostViewGuest::ProcessAckedTouchEvent(
94 const TouchEventWithLatencyInfo
& touch
, InputEventAckState ack_result
) {
95 // TODO(fsamuel): Currently we will only take this codepath if the guest has
96 // requested touch events. A better solution is to always forward touchpresses
97 // to the embedder process to target a BrowserPlugin, and then route all
98 // subsequent touch points of that touchdown to the appropriate guest until
99 // that touch point is released.
100 ScopedVector
<ui::TouchEvent
> events
;
101 if (!MakeUITouchEventsFromWebTouchEvents(touch
, &events
, LOCAL_COORDINATES
))
104 ui::EventResult result
= (ack_result
==
105 INPUT_EVENT_ACK_STATE_CONSUMED
) ? ui::ER_HANDLED
: ui::ER_UNHANDLED
;
106 for (ScopedVector
<ui::TouchEvent
>::iterator iter
= events
.begin(),
107 end
= events
.end(); iter
!= end
; ++iter
) {
108 scoped_ptr
<ui::GestureRecognizer::Gestures
> gestures
;
109 gestures
.reset(gesture_recognizer_
->ProcessTouchEventForGesture(
110 *(*iter
), result
, this));
111 ProcessGestures(gestures
.get());
116 void RenderWidgetHostViewGuest::Show() {
120 void RenderWidgetHostViewGuest::Hide() {
124 bool RenderWidgetHostViewGuest::IsShowing() {
128 gfx::Rect
RenderWidgetHostViewGuest::GetViewBounds() const {
129 gfx::Rect embedder_bounds
= static_cast<RenderWidgetHostViewPort
*>(
130 guest_
->GetEmbedderRenderWidgetHostView())->GetViewBounds();
131 gfx::Rect shifted_rect
= guest_
->ToGuestRect(embedder_bounds
);
132 shifted_rect
.set_width(size_
.width());
133 shifted_rect
.set_height(size_
.height());
137 void RenderWidgetHostViewGuest::RenderViewGone(base::TerminationStatus status
,
139 platform_view_
->RenderViewGone(status
, error_code
);
140 // Destroy the guest view instance only, so we don't end up calling
141 // platform_view_->Destroy().
145 void RenderWidgetHostViewGuest::Destroy() {
146 platform_view_
->Destroy();
147 // The RenderWidgetHost's destruction led here, so don't call it.
151 void RenderWidgetHostViewGuest::SetTooltipText(const string16
& tooltip_text
) {
152 platform_view_
->SetTooltipText(tooltip_text
);
155 void RenderWidgetHostViewGuest::AcceleratedSurfaceBuffersSwapped(
156 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params
& params
,
158 // If accelerated surface buffers are getting swapped then we're not using
159 // the software path.
160 guest_
->clear_damage_buffer();
161 guest_
->SendMessageToEmbedder(
162 new BrowserPluginMsg_BuffersSwapped(
163 guest_
->instance_id(),
170 void RenderWidgetHostViewGuest::AcceleratedSurfacePostSubBuffer(
171 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params
& params
,
176 void RenderWidgetHostViewGuest::OnSwapCompositorFrame(
177 scoped_ptr
<cc::CompositorFrame
> frame
) {
178 if (frame
->software_frame_data
) {
179 cc::SoftwareFrameData
* frame_data
= frame
->software_frame_data
.get();
181 base::SharedMemory
shared_memory(frame_data
->handle
, true,
182 host_
->GetProcess()->GetHandle());
184 base::SharedMemory
shared_memory(frame_data
->handle
, true);
187 RenderWidgetHostView
* embedder_view
=
188 guest_
->GetEmbedderRenderWidgetHostView();
189 base::ProcessHandle embedder_pid
=
190 embedder_view
->GetRenderWidgetHost()->GetProcess()->GetHandle();
192 shared_memory
.GiveToProcess(embedder_pid
, &frame_data
->handle
);
195 guest_
->clear_damage_buffer();
196 guest_
->SendMessageToEmbedder(
197 new BrowserPluginMsg_CompositorFrameSwapped(
198 guest_
->instance_id(),
200 host_
->GetRoutingID(),
201 host_
->GetProcess()->GetID()));
204 void RenderWidgetHostViewGuest::SetBounds(const gfx::Rect
& rect
) {
205 SetSize(rect
.size());
208 bool RenderWidgetHostViewGuest::OnMessageReceived(const IPC::Message
& msg
) {
209 return platform_view_
->OnMessageReceived(msg
);
212 void RenderWidgetHostViewGuest::InitAsChild(
213 gfx::NativeView parent_view
) {
214 platform_view_
->InitAsChild(parent_view
);
217 void RenderWidgetHostViewGuest::InitAsPopup(
218 RenderWidgetHostView
* parent_host_view
, const gfx::Rect
& pos
) {
219 // This should never get called.
223 void RenderWidgetHostViewGuest::InitAsFullscreen(
224 RenderWidgetHostView
* reference_host_view
) {
225 // This should never get called.
229 gfx::NativeView
RenderWidgetHostViewGuest::GetNativeView() const {
230 return guest_
->GetEmbedderRenderWidgetHostView()->GetNativeView();
233 gfx::NativeViewId
RenderWidgetHostViewGuest::GetNativeViewId() const {
234 return guest_
->GetEmbedderRenderWidgetHostView()->GetNativeViewId();
237 gfx::NativeViewAccessible
RenderWidgetHostViewGuest::GetNativeViewAccessible() {
238 return guest_
->GetEmbedderRenderWidgetHostView()->GetNativeViewAccessible();
241 void RenderWidgetHostViewGuest::MovePluginWindows(
242 const gfx::Vector2d
& scroll_offset
,
243 const std::vector
<webkit::npapi::WebPluginGeometry
>& moves
) {
244 platform_view_
->MovePluginWindows(scroll_offset
, moves
);
247 void RenderWidgetHostViewGuest::Focus() {
250 void RenderWidgetHostViewGuest::Blur() {
253 bool RenderWidgetHostViewGuest::HasFocus() const {
257 bool RenderWidgetHostViewGuest::IsSurfaceAvailableForCopy() const {
262 void RenderWidgetHostViewGuest::UpdateCursor(const WebCursor
& cursor
) {
263 platform_view_
->UpdateCursor(cursor
);
266 void RenderWidgetHostViewGuest::SetIsLoading(bool is_loading
) {
267 platform_view_
->SetIsLoading(is_loading
);
270 void RenderWidgetHostViewGuest::TextInputTypeChanged(ui::TextInputType type
,
271 bool can_compose_inline
) {
272 RenderWidgetHostViewPort::FromRWHV(
273 guest_
->GetEmbedderRenderWidgetHostView())->
274 TextInputTypeChanged(type
, can_compose_inline
);
277 void RenderWidgetHostViewGuest::ImeCancelComposition() {
278 platform_view_
->ImeCancelComposition();
281 void RenderWidgetHostViewGuest::ImeCompositionRangeChanged(
282 const ui::Range
& range
,
283 const std::vector
<gfx::Rect
>& character_bounds
) {
286 void RenderWidgetHostViewGuest::DidUpdateBackingStore(
287 const gfx::Rect
& scroll_rect
,
288 const gfx::Vector2d
& scroll_delta
,
289 const std::vector
<gfx::Rect
>& copy_rects
,
290 const ui::LatencyInfo
& latency_info
) {
294 void RenderWidgetHostViewGuest::SelectionBoundsChanged(
295 const ViewHostMsg_SelectionBounds_Params
& params
) {
296 platform_view_
->SelectionBoundsChanged(params
);
299 void RenderWidgetHostViewGuest::ScrollOffsetChanged() {
302 BackingStore
* RenderWidgetHostViewGuest::AllocBackingStore(
303 const gfx::Size
& size
) {
308 void RenderWidgetHostViewGuest::CopyFromCompositingSurface(
309 const gfx::Rect
& src_subrect
,
310 const gfx::Size
& /* dst_size */,
311 const base::Callback
<void(bool, const SkBitmap
&)>& callback
) {
312 callback
.Run(false, SkBitmap());
315 void RenderWidgetHostViewGuest::CopyFromCompositingSurfaceToVideoFrame(
316 const gfx::Rect
& src_subrect
,
317 const scoped_refptr
<media::VideoFrame
>& target
,
318 const base::Callback
<void(bool)>& callback
) {
323 bool RenderWidgetHostViewGuest::CanCopyToVideoFrame() const {
327 void RenderWidgetHostViewGuest::AcceleratedSurfaceSuspend() {
331 void RenderWidgetHostViewGuest::AcceleratedSurfaceRelease() {
334 bool RenderWidgetHostViewGuest::HasAcceleratedSurface(
335 const gfx::Size
& desired_size
) {
339 void RenderWidgetHostViewGuest::SetBackground(const SkBitmap
& background
) {
340 platform_view_
->SetBackground(background
);
343 #if defined(OS_WIN) && !defined(USE_AURA)
344 void RenderWidgetHostViewGuest::SetClickthroughRegion(SkRegion
* region
) {
348 #if defined(OS_WIN) && defined(USE_AURA)
349 gfx::NativeViewAccessible
350 RenderWidgetHostViewGuest::AccessibleObjectFromChildId(long child_id
) {
356 void RenderWidgetHostViewGuest::SetHasHorizontalScrollbar(
357 bool has_horizontal_scrollbar
) {
358 platform_view_
->SetHasHorizontalScrollbar(has_horizontal_scrollbar
);
361 void RenderWidgetHostViewGuest::SetScrollOffsetPinning(
362 bool is_pinned_to_left
, bool is_pinned_to_right
) {
363 platform_view_
->SetScrollOffsetPinning(
364 is_pinned_to_left
, is_pinned_to_right
);
367 void RenderWidgetHostViewGuest::OnAcceleratedCompositingStateChange() {
370 bool RenderWidgetHostViewGuest::LockMouse() {
371 return platform_view_
->LockMouse();
374 void RenderWidgetHostViewGuest::UnlockMouse() {
375 return platform_view_
->UnlockMouse();
378 void RenderWidgetHostViewGuest::GetScreenInfo(WebKit::WebScreenInfo
* results
) {
379 RenderWidgetHostViewPort
* embedder_view
=
380 RenderWidgetHostViewPort::FromRWHV(
381 guest_
->GetEmbedderRenderWidgetHostView());
382 embedder_view
->GetScreenInfo(results
);
385 void RenderWidgetHostViewGuest::OnAccessibilityNotifications(
386 const std::vector
<AccessibilityHostMsg_NotificationParams
>& params
) {
389 #if defined(OS_MACOSX)
390 void RenderWidgetHostViewGuest::SetActive(bool active
) {
391 platform_view_
->SetActive(active
);
394 void RenderWidgetHostViewGuest::SetTakesFocusOnlyOnMouseDown(bool flag
) {
395 platform_view_
->SetTakesFocusOnlyOnMouseDown(flag
);
398 void RenderWidgetHostViewGuest::SetWindowVisibility(bool visible
) {
399 platform_view_
->SetWindowVisibility(visible
);
402 void RenderWidgetHostViewGuest::WindowFrameChanged() {
403 platform_view_
->WindowFrameChanged();
406 void RenderWidgetHostViewGuest::ShowDefinitionForSelection() {
407 platform_view_
->ShowDefinitionForSelection();
410 bool RenderWidgetHostViewGuest::SupportsSpeech() const {
411 return platform_view_
->SupportsSpeech();
414 void RenderWidgetHostViewGuest::SpeakSelection() {
415 platform_view_
->SpeakSelection();
418 bool RenderWidgetHostViewGuest::IsSpeaking() const {
419 return platform_view_
->IsSpeaking();
422 void RenderWidgetHostViewGuest::StopSpeaking() {
423 platform_view_
->StopSpeaking();
426 void RenderWidgetHostViewGuest::AboutToWaitForBackingStoreMsg() {
430 bool RenderWidgetHostViewGuest::PostProcessEventForPluginIme(
431 const NativeWebKeyboardEvent
& event
) {
435 #endif // defined(OS_MACOSX)
437 #if defined(OS_ANDROID)
438 void RenderWidgetHostViewGuest::ShowDisambiguationPopup(
439 const gfx::Rect
& target_rect
,
440 const SkBitmap
& zoomed_bitmap
) {
443 void RenderWidgetHostViewGuest::HasTouchEventHandlers(bool need_touch_events
) {
445 #endif // defined(OS_ANDROID)
447 #if defined(TOOLKIT_GTK)
448 GdkEventButton
* RenderWidgetHostViewGuest::GetLastMouseDown() {
452 gfx::NativeView
RenderWidgetHostViewGuest::BuildInputMethodsGtkMenu() {
453 return platform_view_
->BuildInputMethodsGtkMenu();
455 #endif // defined(TOOLKIT_GTK)
457 #if defined(OS_WIN) && !defined(USE_AURA)
458 void RenderWidgetHostViewGuest::WillWmDestroy() {
462 #if defined(OS_WIN) && defined(USE_AURA)
463 void RenderWidgetHostViewGuest::SetParentNativeViewAccessible(
464 gfx::NativeViewAccessible accessible_parent
) {
468 void RenderWidgetHostViewGuest::DestroyGuestView() {
470 base::MessageLoop::current()->DeleteSoon(FROM_HERE
, this);
473 bool RenderWidgetHostViewGuest::DispatchLongPressGestureEvent(
474 ui::GestureEvent
* event
) {
475 return ForwardGestureEventToRenderer(event
);
478 bool RenderWidgetHostViewGuest::DispatchCancelTouchEvent(
479 ui::TouchEvent
* event
) {
483 WebKit::WebTouchEvent cancel_event
;
484 cancel_event
.type
= WebKit::WebInputEvent::TouchCancel
;
485 cancel_event
.timeStampSeconds
= event
->time_stamp().InSecondsF();
486 host_
->ForwardTouchEventWithLatencyInfo(cancel_event
, *event
->latency());
490 bool RenderWidgetHostViewGuest::ForwardGestureEventToRenderer(
491 ui::GestureEvent
* gesture
) {
492 #if defined(OS_WIN) || defined(USE_AURA)
496 // Pinch gestures are disabled by default on windows desktop. See
497 // crbug.com/128477 and crbug.com/148816
498 if ((gesture
->type() == ui::ET_GESTURE_PINCH_BEGIN
||
499 gesture
->type() == ui::ET_GESTURE_PINCH_UPDATE
||
500 gesture
->type() == ui::ET_GESTURE_PINCH_END
) &&
501 !ShouldSendPinchGesture()) {
505 WebKit::WebGestureEvent web_gesture
=
506 MakeWebGestureEventFromUIEvent(*gesture
);
507 const gfx::Point
& client_point
= gesture
->location();
508 const gfx::Point
& screen_point
= gesture
->location();
510 web_gesture
.x
= client_point
.x();
511 web_gesture
.y
= client_point
.y();
512 web_gesture
.globalX
= screen_point
.x();
513 web_gesture
.globalY
= screen_point
.y();
515 if (web_gesture
.type
== WebKit::WebGestureEvent::Undefined
)
517 if (web_gesture
.type
== WebKit::WebGestureEvent::GestureTapDown
) {
518 host_
->ForwardGestureEvent(
519 CreateFlingCancelEvent(gesture
->time_stamp().InSecondsF()));
521 host_
->ForwardGestureEvent(web_gesture
);
528 void RenderWidgetHostViewGuest::ProcessGestures(
529 ui::GestureRecognizer::Gestures
* gestures
) {
530 if ((gestures
== NULL
) || gestures
->empty())
532 for (ui::GestureRecognizer::Gestures::iterator g_it
= gestures
->begin();
533 g_it
!= gestures
->end();
535 ForwardGestureEventToRenderer(*g_it
);
540 } // namespace content