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_impl.h"
10 #include "base/auto_reset.h"
11 #include "base/bind.h"
12 #include "base/command_line.h"
13 #include "base/containers/hash_tables.h"
14 #include "base/debug/trace_event.h"
15 #include "base/i18n/rtl.h"
16 #include "base/lazy_instance.h"
17 #include "base/message_loop.h"
18 #include "base/metrics/field_trial.h"
19 #include "base/metrics/histogram.h"
20 #include "base/strings/string_number_conversions.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "cc/output/compositor_frame.h"
23 #include "cc/output/compositor_frame_ack.h"
24 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
25 #include "content/browser/gpu/gpu_process_host.h"
26 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
27 #include "content/browser/gpu/gpu_surface_tracker.h"
28 #include "content/browser/renderer_host/backing_store.h"
29 #include "content/browser/renderer_host/backing_store_manager.h"
30 #include "content/browser/renderer_host/dip_util.h"
31 #include "content/browser/renderer_host/gesture_event_filter.h"
32 #include "content/browser/renderer_host/overscroll_controller.h"
33 #include "content/browser/renderer_host/render_process_host_impl.h"
34 #include "content/browser/renderer_host/render_view_host_impl.h"
35 #include "content/browser/renderer_host/render_widget_helper.h"
36 #include "content/browser/renderer_host/render_widget_host_delegate.h"
37 #include "content/browser/renderer_host/touch_event_queue.h"
38 #include "content/browser/renderer_host/touchpad_tap_suppression_controller.h"
39 #include "content/common/accessibility_messages.h"
40 #include "content/common/content_constants_internal.h"
41 #include "content/common/gpu/gpu_messages.h"
42 #include "content/common/input_messages.h"
43 #include "content/common/view_messages.h"
44 #include "content/port/browser/render_widget_host_view_port.h"
45 #include "content/public/browser/compositor_util.h"
46 #include "content/public/browser/native_web_keyboard_event.h"
47 #include "content/public/browser/notification_service.h"
48 #include "content/public/browser/notification_types.h"
49 #include "content/public/browser/user_metrics.h"
50 #include "content/public/common/content_constants.h"
51 #include "content/public/common/content_switches.h"
52 #include "content/public/common/result_codes.h"
53 #include "skia/ext/image_operations.h"
54 #include "skia/ext/platform_canvas.h"
55 #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
56 #include "ui/base/events/event.h"
57 #include "ui/base/keycodes/keyboard_codes.h"
58 #include "ui/gfx/size_conversions.h"
59 #include "ui/gfx/skbitmap_operations.h"
60 #include "ui/gfx/vector2d_conversions.h"
61 #include "webkit/common/cursors/webcursor.h"
62 #include "webkit/common/webpreferences.h"
63 #include "webkit/plugins/npapi/webplugin.h"
64 #include "webkit/plugins/npapi/webplugin_delegate_impl.h"
66 #if defined(TOOLKIT_GTK)
67 #include "content/browser/renderer_host/backing_store_gtk.h"
68 #elif defined(OS_MACOSX)
69 #include "content/browser/renderer_host/backing_store_mac.h"
73 using base::TimeDelta
;
74 using base::TimeTicks
;
75 using webkit::npapi::WebPluginDelegateImpl
;
76 using WebKit::WebGestureEvent
;
77 using WebKit::WebInputEvent
;
78 using WebKit::WebKeyboardEvent
;
79 using WebKit::WebMouseEvent
;
80 using WebKit::WebMouseWheelEvent
;
81 using WebKit::WebTextDirection
;
86 bool g_check_for_pending_resize_ack
= true;
88 // How long to (synchronously) wait for the renderer to respond with a
89 // PaintRect message, when our backing-store is invalid, before giving up and
90 // returning a null or incorrectly sized backing-store from GetBackingStore.
91 // This timeout impacts the "choppiness" of our window resize perf.
92 const int kPaintMsgTimeoutMS
= 50;
94 // Returns |true| if the two wheel events should be coalesced.
95 bool ShouldCoalesceMouseWheelEvents(const WebMouseWheelEvent
& last_event
,
96 const WebMouseWheelEvent
& new_event
) {
97 return last_event
.modifiers
== new_event
.modifiers
&&
98 last_event
.scrollByPage
== new_event
.scrollByPage
&&
99 last_event
.hasPreciseScrollingDeltas
100 == new_event
.hasPreciseScrollingDeltas
&&
101 last_event
.phase
== new_event
.phase
&&
102 last_event
.momentumPhase
== new_event
.momentumPhase
;
105 float GetUnacceleratedDelta(float accelerated_delta
, float acceleration_ratio
) {
106 return accelerated_delta
* acceleration_ratio
;
109 float GetAccelerationRatio(float accelerated_delta
, float unaccelerated_delta
) {
110 if (unaccelerated_delta
== 0.f
|| accelerated_delta
== 0.f
)
112 return unaccelerated_delta
/ accelerated_delta
;
115 base::LazyInstance
<std::vector
<RenderWidgetHost::CreatedCallback
> >
116 g_created_callbacks
= LAZY_INSTANCE_INITIALIZER
;
121 typedef std::pair
<int32
, int32
> RenderWidgetHostID
;
122 typedef base::hash_map
<RenderWidgetHostID
, RenderWidgetHostImpl
*>
124 static base::LazyInstance
<RoutingIDWidgetMap
> g_routing_id_widget_map
=
125 LAZY_INSTANCE_INITIALIZER
;
128 void RenderWidgetHost::RemoveAllBackingStores() {
129 BackingStoreManager::RemoveAllBackingStores();
133 size_t RenderWidgetHost::BackingStoreMemorySize() {
134 return BackingStoreManager::MemorySize();
137 ///////////////////////////////////////////////////////////////////////////////
138 // RenderWidgetHostImpl
140 RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate
* delegate
,
141 RenderProcessHost
* process
,
144 renderer_initialized_(false),
145 hung_renderer_delay_ms_(kHungRendererDelayMs
),
148 routing_id_(routing_id
),
152 is_fullscreen_(false),
153 is_accelerated_compositing_active_(false),
154 repaint_ack_pending_(false),
155 resize_ack_pending_(false),
156 screen_info_out_of_date_(false),
157 overdraw_bottom_height_(0.f
),
158 should_auto_resize_(false),
159 waiting_for_screen_rects_ack_(false),
160 mouse_move_pending_(false),
161 mouse_wheel_pending_(false),
162 accessibility_mode_(AccessibilityModeOff
),
163 select_range_pending_(false),
164 move_caret_pending_(false),
165 needs_repainting_on_restore_(false),
166 is_unresponsive_(false),
167 in_flight_event_count_(0),
168 in_get_backing_store_(false),
169 abort_get_backing_store_(false),
170 view_being_painted_(false),
171 ignore_input_events_(false),
172 input_method_active_(false),
173 text_direction_updated_(false),
174 text_direction_(WebKit::WebTextDirectionLeftToRight
),
175 text_direction_canceled_(false),
176 suppress_next_char_events_(false),
177 pending_mouse_lock_request_(false),
178 allow_privileged_mouse_lock_(false),
179 has_touch_handler_(false),
181 touch_event_queue_(new TouchEventQueue(this)),
182 gesture_event_filter_(new GestureEventFilter(this)),
183 last_input_number_(0) {
185 if (routing_id_
== MSG_ROUTING_NONE
) {
186 routing_id_
= process_
->GetNextRoutingID();
187 surface_id_
= GpuSurfaceTracker::Get()->AddSurfaceForRenderer(
191 // TODO(piman): This is a O(N) lookup, where we could forward the
192 // information from the RenderWidgetHelper. The problem is that doing so
193 // currently leaks outside of content all the way to chrome classes, and
194 // would be a layering violation. Since we don't expect more than a few
195 // hundreds of RWH, this seems acceptable. Revisit if performance become a
196 // problem, for example by tracking in the RenderWidgetHelper the routing id
197 // (and surface id) that have been created, but whose RWH haven't yet.
198 surface_id_
= GpuSurfaceTracker::Get()->LookupSurfaceForRenderer(
204 is_threaded_compositing_enabled_
= IsThreadedCompositingEnabled();
206 g_routing_id_widget_map
.Get().insert(std::make_pair(
207 RenderWidgetHostID(process
->GetID(), routing_id_
), this));
208 process_
->AddRoute(routing_id_
, this);
209 // Because the widget initializes as is_hidden_ == false,
210 // tell the process host that we're alive.
211 process_
->WidgetRestored();
213 accessibility_mode_
=
214 BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode();
216 for (size_t i
= 0; i
< g_created_callbacks
.Get().size(); i
++)
217 g_created_callbacks
.Get().at(i
).Run(this);
219 #if defined(USE_AURA)
220 bool overscroll_enabled
= CommandLine::ForCurrentProcess()->
221 GetSwitchValueASCII(switches::kOverscrollHistoryNavigation
) != "0";
222 SetOverscrollControllerEnabled(overscroll_enabled
);
226 RenderWidgetHostImpl::~RenderWidgetHostImpl() {
229 // Clear our current or cached backing store if either remains.
230 BackingStoreManager::RemoveBackingStore(this);
232 GpuSurfaceTracker::Get()->RemoveSurface(surface_id_
);
235 process_
->RemoveRoute(routing_id_
);
236 g_routing_id_widget_map
.Get().erase(
237 RenderWidgetHostID(process_
->GetID(), routing_id_
));
240 delegate_
->RenderWidgetDeleted(this);
244 RenderWidgetHost
* RenderWidgetHost::FromID(
247 return RenderWidgetHostImpl::FromID(process_id
, routing_id
);
251 RenderWidgetHostImpl
* RenderWidgetHostImpl::FromID(
254 RoutingIDWidgetMap
* widgets
= g_routing_id_widget_map
.Pointer();
255 RoutingIDWidgetMap::iterator it
= widgets
->find(
256 RenderWidgetHostID(process_id
, routing_id
));
257 return it
== widgets
->end() ? NULL
: it
->second
;
261 std::vector
<RenderWidgetHost
*> RenderWidgetHost::GetRenderWidgetHosts() {
262 std::vector
<RenderWidgetHost
*> hosts
;
263 RoutingIDWidgetMap
* widgets
= g_routing_id_widget_map
.Pointer();
264 for (RoutingIDWidgetMap::const_iterator it
= widgets
->begin();
265 it
!= widgets
->end();
267 hosts
.push_back(it
->second
);
273 RenderWidgetHostImpl
* RenderWidgetHostImpl::From(RenderWidgetHost
* rwh
) {
274 return rwh
->AsRenderWidgetHostImpl();
278 void RenderWidgetHost::AddCreatedCallback(const CreatedCallback
& callback
) {
279 g_created_callbacks
.Get().push_back(callback
);
283 void RenderWidgetHost::RemoveCreatedCallback(const CreatedCallback
& callback
) {
284 for (size_t i
= 0; i
< g_created_callbacks
.Get().size(); ++i
) {
285 if (g_created_callbacks
.Get().at(i
).Equals(callback
)) {
286 g_created_callbacks
.Get().erase(g_created_callbacks
.Get().begin() + i
);
292 void RenderWidgetHostImpl::SetView(RenderWidgetHostView
* view
) {
293 view_
= RenderWidgetHostViewPort::FromRWHV(view
);
296 GpuSurfaceTracker::Get()->SetSurfaceHandle(
297 surface_id_
, gfx::GLSurfaceHandle());
301 RenderProcessHost
* RenderWidgetHostImpl::GetProcess() const {
305 int RenderWidgetHostImpl::GetRoutingID() const {
309 RenderWidgetHostView
* RenderWidgetHostImpl::GetView() const {
313 RenderWidgetHostImpl
* RenderWidgetHostImpl::AsRenderWidgetHostImpl() {
317 gfx::NativeViewId
RenderWidgetHostImpl::GetNativeViewId() const {
319 return view_
->GetNativeViewId();
323 gfx::GLSurfaceHandle
RenderWidgetHostImpl::GetCompositingSurface() {
325 return view_
->GetCompositingSurface();
326 return gfx::GLSurfaceHandle();
329 void RenderWidgetHostImpl::CompositingSurfaceUpdated() {
330 GpuSurfaceTracker::Get()->SetSurfaceHandle(
331 surface_id_
, GetCompositingSurface());
332 process_
->SurfaceUpdated(surface_id_
);
335 void RenderWidgetHostImpl::ResetSizeAndRepaintPendingFlags() {
336 resize_ack_pending_
= false;
337 if (repaint_ack_pending_
) {
338 TRACE_EVENT_ASYNC_END0(
339 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
341 repaint_ack_pending_
= false;
342 in_flight_size_
.SetSize(0, 0);
345 void RenderWidgetHostImpl::SendScreenRects() {
346 if (!renderer_initialized_
|| waiting_for_screen_rects_ack_
)
350 // On GTK, this comes in for backgrounded tabs. Ignore, to match what
351 // happens on Win & Mac, and when the view is shown it'll call this again.
358 last_view_screen_rect_
= view_
->GetViewBounds();
359 last_window_screen_rect_
= view_
->GetBoundsInRootWindow();
360 Send(new ViewMsg_UpdateScreenRects(
361 GetRoutingID(), last_view_screen_rect_
, last_window_screen_rect_
));
363 delegate_
->DidSendScreenRects(this);
364 waiting_for_screen_rects_ack_
= true;
368 RenderWidgetHostImpl::GetSyntheticScrollMessageInterval() const {
369 return smooth_scroll_gesture_controller_
.GetSyntheticScrollMessageInterval();
372 void RenderWidgetHostImpl::SetOverscrollControllerEnabled(bool enabled
) {
374 overscroll_controller_
.reset();
375 else if (!overscroll_controller_
)
376 overscroll_controller_
.reset(new OverscrollController(this));
379 void RenderWidgetHostImpl::SuppressNextCharEvents() {
380 suppress_next_char_events_
= true;
383 void RenderWidgetHostImpl::Init() {
384 DCHECK(process_
->HasConnection());
386 renderer_initialized_
= true;
388 GpuSurfaceTracker::Get()->SetSurfaceHandle(
389 surface_id_
, GetCompositingSurface());
391 // Send the ack along with the information on placement.
392 Send(new ViewMsg_CreatingNew_ACK(routing_id_
));
393 GetProcess()->ResumeRequestsForView(routing_id_
);
398 void RenderWidgetHostImpl::Shutdown() {
399 RejectMouseLockOrUnlockIfNecessary();
401 if (process_
->HasConnection()) {
402 // Tell the renderer object to close.
403 bool rv
= Send(new ViewMsg_Close(routing_id_
));
410 bool RenderWidgetHostImpl::IsLoading() const {
414 bool RenderWidgetHostImpl::IsRenderView() const {
418 bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message
&msg
) {
420 bool msg_is_ok
= true;
421 IPC_BEGIN_MESSAGE_MAP_EX(RenderWidgetHostImpl
, msg
, msg_is_ok
)
422 IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewReady
, OnRenderViewReady
)
423 IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewGone
, OnRenderViewGone
)
424 IPC_MESSAGE_HANDLER(ViewHostMsg_Close
, OnClose
)
425 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateScreenRects_ACK
,
426 OnUpdateScreenRectsAck
)
427 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove
, OnRequestMove
)
428 IPC_MESSAGE_HANDLER(ViewHostMsg_SetTooltipText
, OnSetTooltipText
)
429 IPC_MESSAGE_HANDLER(ViewHostMsg_PaintAtSize_ACK
, OnPaintAtSizeAck
)
430 IPC_MESSAGE_HANDLER(ViewHostMsg_CompositorSurfaceBuffersSwapped
,
431 OnCompositorSurfaceBuffersSwapped
)
432 IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_SwapCompositorFrame
,
433 msg_is_ok
= OnSwapCompositorFrame(msg
))
434 IPC_MESSAGE_HANDLER(ViewHostMsg_DidOverscroll
, OnOverscrolled
)
435 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect
, OnUpdateRect
)
436 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateIsDelayed
, OnUpdateIsDelayed
)
437 IPC_MESSAGE_HANDLER(InputHostMsg_HandleInputEvent_ACK
, OnInputEventAck
)
438 IPC_MESSAGE_HANDLER(ViewHostMsg_BeginSmoothScroll
, OnBeginSmoothScroll
)
439 IPC_MESSAGE_HANDLER(ViewHostMsg_SelectRange_ACK
, OnSelectRangeAck
)
440 IPC_MESSAGE_HANDLER(ViewHostMsg_MoveCaret_ACK
, OnMsgMoveCaretAck
)
441 IPC_MESSAGE_HANDLER(ViewHostMsg_Focus
, OnFocus
)
442 IPC_MESSAGE_HANDLER(ViewHostMsg_Blur
, OnBlur
)
443 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers
,
444 OnHasTouchEventHandlers
)
445 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor
, OnSetCursor
)
446 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputTypeChanged
,
447 OnTextInputTypeChanged
)
448 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCompositionRangeChanged
,
449 OnImeCompositionRangeChanged
)
450 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCancelComposition
,
451 OnImeCancelComposition
)
452 IPC_MESSAGE_HANDLER(ViewHostMsg_DidActivateAcceleratedCompositing
,
453 OnDidActivateAcceleratedCompositing
)
454 IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse
, OnLockMouse
)
455 IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse
, OnUnlockMouse
)
456 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowDisambiguationPopup
,
457 OnShowDisambiguationPopup
)
459 IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowCreated
,
460 OnWindowlessPluginDummyWindowCreated
)
461 IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowDestroyed
,
462 OnWindowlessPluginDummyWindowDestroyed
)
464 IPC_MESSAGE_HANDLER(ViewHostMsg_Snapshot
, OnSnapshot
)
465 IPC_MESSAGE_UNHANDLED(handled
= false)
466 IPC_END_MESSAGE_MAP_EX()
468 if (!handled
&& view_
&& view_
->OnMessageReceived(msg
))
472 // The message de-serialization failed. Kill the renderer process.
473 RecordAction(UserMetricsAction("BadMessageTerminate_RWH"));
474 GetProcess()->ReceivedBadMessage();
479 bool RenderWidgetHostImpl::Send(IPC::Message
* msg
) {
480 return process_
->Send(msg
);
483 void RenderWidgetHostImpl::WasHidden() {
486 // Don't bother reporting hung state when we aren't active.
487 StopHangMonitorTimeout();
489 // If we have a renderer, then inform it that we are being hidden so it can
490 // reduce its resource utilization.
491 Send(new ViewMsg_WasHidden(routing_id_
));
493 // Tell the RenderProcessHost we were hidden.
494 process_
->WidgetHidden();
496 bool is_visible
= false;
497 NotificationService::current()->Notify(
498 NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED
,
499 Source
<RenderWidgetHost
>(this),
500 Details
<bool>(&is_visible
));
503 void RenderWidgetHostImpl::WasShown() {
504 // When we create the widget, it is created as *not* hidden.
511 BackingStore
* backing_store
= BackingStoreManager::Lookup(this);
512 // If we already have a backing store for this widget, then we don't need to
513 // repaint on restore _unless_ we know that our backing store is invalid.
514 // When accelerated compositing is on, we must always repaint, even when
515 // the backing store exists.
516 bool needs_repainting
;
517 if (needs_repainting_on_restore_
|| !backing_store
||
518 is_accelerated_compositing_active()) {
519 needs_repainting
= true;
520 needs_repainting_on_restore_
= false;
522 needs_repainting
= false;
524 Send(new ViewMsg_WasShown(routing_id_
, needs_repainting
));
526 process_
->WidgetRestored();
528 bool is_visible
= true;
529 NotificationService::current()->Notify(
530 NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED
,
531 Source
<RenderWidgetHost
>(this),
532 Details
<bool>(&is_visible
));
534 // It's possible for our size to be out of sync with the renderer. The
535 // following is one case that leads to this:
536 // 1. WasResized -> Send ViewMsg_Resize to render
537 // 2. WasResized -> do nothing as resize_ack_pending_ is true
539 // 4. OnUpdateRect from (1) processed. Does NOT invoke WasResized as view
540 // is hidden. Now renderer/browser out of sync with what they think size
542 // By invoking WasResized the renderer is updated as necessary. WasResized
543 // does nothing if the sizes are already in sync.
545 // TODO: ideally ViewMsg_WasShown would take a size. This way, the renderer
546 // could handle both the restore and resize at once. This isn't that big a
547 // deal as RenderWidget::WasShown delays updating, so that the resize from
548 // WasResized is usually processed before the renderer is painted.
552 void RenderWidgetHostImpl::WasResized() {
553 if (resize_ack_pending_
|| !process_
->HasConnection() || !view_
||
554 !renderer_initialized_
|| should_auto_resize_
) {
558 gfx::Rect view_bounds
= view_
->GetViewBounds();
559 gfx::Size
new_size(view_bounds
.size());
561 gfx::Size old_physical_backing_size
= physical_backing_size_
;
562 physical_backing_size_
= view_
->GetPhysicalBackingSize();
563 bool was_fullscreen
= is_fullscreen_
;
564 is_fullscreen_
= IsFullscreen();
565 float old_overdraw_bottom_height
= overdraw_bottom_height_
;
566 overdraw_bottom_height_
= view_
->GetOverdrawBottomHeight();
568 bool size_changed
= new_size
!= current_size_
;
569 bool side_payload_changed
=
570 screen_info_out_of_date_
||
571 old_physical_backing_size
!= physical_backing_size_
||
572 was_fullscreen
!= is_fullscreen_
||
573 old_overdraw_bottom_height
!= overdraw_bottom_height_
;
575 if (!size_changed
&& !side_payload_changed
)
578 if (in_flight_size_
!= gfx::Size() && new_size
== in_flight_size_
&&
579 !side_payload_changed
)
583 screen_info_
.reset(new WebKit::WebScreenInfo
);
584 GetWebScreenInfo(screen_info_
.get());
587 // We don't expect to receive an ACK when the requested size or the physical
588 // backing size is empty, or when the main viewport size didn't change.
589 if (!new_size
.IsEmpty() && !physical_backing_size_
.IsEmpty() && size_changed
)
590 resize_ack_pending_
= g_check_for_pending_resize_ack
;
592 ViewMsg_Resize_Params params
;
593 params
.screen_info
= *screen_info_
;
594 params
.new_size
= new_size
;
595 params
.physical_backing_size
= physical_backing_size_
;
596 params
.overdraw_bottom_height
= overdraw_bottom_height_
;
597 params
.resizer_rect
= GetRootWindowResizerRect();
598 params
.is_fullscreen
= is_fullscreen_
;
599 if (!Send(new ViewMsg_Resize(routing_id_
, params
))) {
600 resize_ack_pending_
= false;
602 in_flight_size_
= new_size
;
606 void RenderWidgetHostImpl::ResizeRectChanged(const gfx::Rect
& new_rect
) {
607 Send(new ViewMsg_ChangeResizeRect(routing_id_
, new_rect
));
610 void RenderWidgetHostImpl::GotFocus() {
614 void RenderWidgetHostImpl::Focus() {
615 Send(new InputMsg_SetFocus(routing_id_
, true));
618 void RenderWidgetHostImpl::Blur() {
619 // If there is a pending mouse lock request, we don't want to reject it at
620 // this point. The user can switch focus back to this view and approve the
623 view_
->UnlockMouse();
625 // If there is a pending overscroll, then that should be cancelled.
626 if (overscroll_controller_
)
627 overscroll_controller_
->Cancel();
629 Send(new InputMsg_SetFocus(routing_id_
, false));
632 void RenderWidgetHostImpl::LostCapture() {
633 Send(new InputMsg_MouseCaptureLost(routing_id_
));
636 void RenderWidgetHostImpl::SetActive(bool active
) {
637 Send(new ViewMsg_SetActive(routing_id_
, active
));
640 void RenderWidgetHostImpl::LostMouseLock() {
641 Send(new ViewMsg_MouseLockLost(routing_id_
));
644 void RenderWidgetHostImpl::ViewDestroyed() {
645 RejectMouseLockOrUnlockIfNecessary();
647 // TODO(evanm): tracking this may no longer be necessary;
648 // eliminate this function if so.
652 void RenderWidgetHostImpl::SetIsLoading(bool is_loading
) {
653 is_loading_
= is_loading
;
656 view_
->SetIsLoading(is_loading
);
659 void RenderWidgetHostImpl::CopyFromBackingStore(
660 const gfx::Rect
& src_subrect
,
661 const gfx::Size
& accelerated_dst_size
,
662 const base::Callback
<void(bool, const SkBitmap
&)>& callback
) {
663 if (view_
&& is_accelerated_compositing_active_
) {
664 TRACE_EVENT0("browser",
665 "RenderWidgetHostImpl::CopyFromBackingStore::FromCompositingSurface");
666 gfx::Rect accelerated_copy_rect
= src_subrect
.IsEmpty() ?
667 gfx::Rect(view_
->GetViewBounds().size()) : src_subrect
;
668 view_
->CopyFromCompositingSurface(accelerated_copy_rect
,
669 accelerated_dst_size
,
674 BackingStore
* backing_store
= GetBackingStore(false);
675 if (!backing_store
) {
676 callback
.Run(false, SkBitmap());
680 TRACE_EVENT0("browser",
681 "RenderWidgetHostImpl::CopyFromBackingStore::FromBackingStore");
682 gfx::Rect copy_rect
= src_subrect
.IsEmpty() ?
683 gfx::Rect(backing_store
->size()) : src_subrect
;
684 // When the result size is equal to the backing store size, copy from the
685 // backing store directly to the output canvas.
686 skia::PlatformBitmap output
;
687 bool result
= backing_store
->CopyFromBackingStore(copy_rect
, &output
);
688 callback
.Run(result
, output
.GetBitmap());
691 #if defined(TOOLKIT_GTK)
692 bool RenderWidgetHostImpl::CopyFromBackingStoreToGtkWindow(
693 const gfx::Rect
& dest_rect
, GdkWindow
* target
) {
694 BackingStore
* backing_store
= GetBackingStore(false);
697 (static_cast<BackingStoreGtk
*>(backing_store
))->PaintToRect(
701 #elif defined(OS_MACOSX)
702 gfx::Size
RenderWidgetHostImpl::GetBackingStoreSize() {
703 BackingStore
* backing_store
= GetBackingStore(false);
704 return backing_store
? backing_store
->size() : gfx::Size();
707 bool RenderWidgetHostImpl::CopyFromBackingStoreToCGContext(
708 const CGRect
& dest_rect
, CGContextRef target
) {
709 BackingStore
* backing_store
= GetBackingStore(false);
712 (static_cast<BackingStoreMac
*>(backing_store
))->
713 CopyFromBackingStoreToCGContext(dest_rect
, target
);
718 void RenderWidgetHostImpl::PaintAtSize(TransportDIB::Handle dib_handle
,
720 const gfx::Size
& page_size
,
721 const gfx::Size
& desired_size
) {
722 // Ask the renderer to create a bitmap regardless of whether it's
723 // hidden, being resized, redrawn, etc. It resizes the web widget
724 // to the page_size and then scales it to the desired_size.
725 Send(new ViewMsg_PaintAtSize(routing_id_
, dib_handle
, tag
,
726 page_size
, desired_size
));
729 bool RenderWidgetHostImpl::TryGetBackingStore(const gfx::Size
& desired_size
,
730 BackingStore
** backing_store
) {
731 // Check if the view has an accelerated surface of the desired size.
732 if (view_
->HasAcceleratedSurface(desired_size
)) {
733 *backing_store
= NULL
;
737 // Check for a software backing store of the desired size.
738 *backing_store
= BackingStoreManager::GetBackingStore(this, desired_size
);
739 return !!*backing_store
;
742 BackingStore
* RenderWidgetHostImpl::GetBackingStore(bool force_create
) {
746 // The view_size will be current_size_ for auto-sized views and otherwise the
747 // size of the view_. (For auto-sized views, current_size_ is updated during
748 // UpdateRect messages.)
749 gfx::Size view_size
= current_size_
;
750 if (!should_auto_resize_
) {
751 // Get the desired size from the current view bounds.
752 gfx::Rect view_rect
= view_
->GetViewBounds();
753 if (view_rect
.IsEmpty())
755 view_size
= view_rect
.size();
758 TRACE_EVENT2("renderer_host", "RenderWidgetHostImpl::GetBackingStore",
759 "width", base::IntToString(view_size
.width()),
760 "height", base::IntToString(view_size
.height()));
762 // We should not be asked to paint while we are hidden. If we are hidden,
763 // then it means that our consumer failed to call WasShown. If we're not
764 // force creating the backing store, it's OK since we can feel free to give
765 // out our cached one if we have it.
766 DCHECK(!is_hidden_
|| !force_create
) <<
767 "GetBackingStore called while hidden!";
769 // We should never be called recursively; this can theoretically lead to
770 // infinite recursion and almost certainly leads to lower performance.
771 DCHECK(!in_get_backing_store_
) << "GetBackingStore called recursively!";
772 base::AutoReset
<bool> auto_reset_in_get_backing_store(
773 &in_get_backing_store_
, true);
775 // We might have a cached backing store that we can reuse!
776 BackingStore
* backing_store
= NULL
;
777 if (TryGetBackingStore(view_size
, &backing_store
) || !force_create
)
778 return backing_store
;
780 // We do not have a suitable backing store in the cache, so send out a
781 // request to the renderer to paint the view if required.
782 if (!repaint_ack_pending_
&& !resize_ack_pending_
&& !view_being_painted_
) {
783 repaint_start_time_
= TimeTicks::Now();
784 repaint_ack_pending_
= true;
785 TRACE_EVENT_ASYNC_BEGIN0(
786 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
787 Send(new ViewMsg_Repaint(routing_id_
, view_size
));
790 TimeDelta max_delay
= TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS
);
791 TimeTicks end_time
= TimeTicks::Now() + max_delay
;
793 TRACE_EVENT0("renderer_host", "GetBackingStore::WaitForUpdate");
795 #if defined(OS_MACOSX)
796 view_
->AboutToWaitForBackingStoreMsg();
799 // When we have asked the RenderWidget to resize, and we are still waiting
800 // on a response, block for a little while to see if we can't get a response
801 // before returning the old (incorrectly sized) backing store.
803 if (process_
->WaitForBackingStoreMsg(routing_id_
, max_delay
, &msg
)) {
804 OnMessageReceived(msg
);
806 // For auto-resized views, current_size_ determines the view_size and it
807 // may have changed during the handling of an UpdateRect message.
808 if (should_auto_resize_
)
809 view_size
= current_size_
;
811 // Break now if we got a backing store or accelerated surface of the
813 if (TryGetBackingStore(view_size
, &backing_store
) ||
814 abort_get_backing_store_
) {
815 abort_get_backing_store_
= false;
816 return backing_store
;
819 TRACE_EVENT0("renderer_host", "GetBackingStore::Timeout");
823 // Loop if we still have time left and haven't gotten a properly sized
824 // BackingStore yet. This is necessary to support the GPU path which
825 // typically has multiple frames pipelined -- we may need to skip one or two
826 // BackingStore messages to get to the latest.
827 max_delay
= end_time
- TimeTicks::Now();
828 } while (max_delay
> TimeDelta::FromSeconds(0));
830 // We have failed to get a backing store of view_size. Fall back on
831 // current_size_ to avoid a white flash while resizing slow pages.
832 if (view_size
!= current_size_
)
833 TryGetBackingStore(current_size_
, &backing_store
);
834 return backing_store
;
837 BackingStore
* RenderWidgetHostImpl::AllocBackingStore(const gfx::Size
& size
) {
840 return view_
->AllocBackingStore(size
);
843 void RenderWidgetHostImpl::DonePaintingToBackingStore() {
844 Send(new ViewMsg_UpdateRect_ACK(GetRoutingID()));
847 void RenderWidgetHostImpl::ScheduleComposite() {
848 if (is_hidden_
|| !is_accelerated_compositing_active_
||
849 current_size_
.IsEmpty()) {
853 // Send out a request to the renderer to paint the view if required.
854 if (!repaint_ack_pending_
&& !resize_ack_pending_
&& !view_being_painted_
) {
855 repaint_start_time_
= TimeTicks::Now();
856 repaint_ack_pending_
= true;
857 TRACE_EVENT_ASYNC_BEGIN0(
858 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
859 Send(new ViewMsg_Repaint(routing_id_
, current_size_
));
863 void RenderWidgetHostImpl::StartHangMonitorTimeout(TimeDelta delay
) {
864 if (!GetProcess()->IsGuest() && CommandLine::ForCurrentProcess()->HasSwitch(
865 switches::kDisableHangMonitor
)) {
869 // Set time_when_considered_hung_ if it's null. Also, update
870 // time_when_considered_hung_ if the caller's request is sooner than the
871 // existing one. This will have the side effect that the existing timeout will
873 Time requested_end_time
= Time::Now() + delay
;
874 if (time_when_considered_hung_
.is_null() ||
875 time_when_considered_hung_
> requested_end_time
)
876 time_when_considered_hung_
= requested_end_time
;
878 // If we already have a timer with the same or shorter duration, then we can
879 // wait for it to finish.
880 if (hung_renderer_timer_
.IsRunning() &&
881 hung_renderer_timer_
.GetCurrentDelay() <= delay
) {
882 // If time_when_considered_hung_ was null, this timer may fire early.
883 // CheckRendererIsUnresponsive handles that by calling
884 // StartHangMonitorTimeout with the remaining time.
885 // If time_when_considered_hung_ was non-null, it means we still haven't
886 // heard from the renderer so we leave time_when_considered_hung_ as is.
890 // Either the timer is not yet running, or we need to adjust the timer to
892 time_when_considered_hung_
= requested_end_time
;
893 hung_renderer_timer_
.Stop();
894 hung_renderer_timer_
.Start(FROM_HERE
, delay
, this,
895 &RenderWidgetHostImpl::CheckRendererIsUnresponsive
);
898 void RenderWidgetHostImpl::RestartHangMonitorTimeout() {
899 // Setting to null will cause StartHangMonitorTimeout to restart the timer.
900 time_when_considered_hung_
= Time();
901 StartHangMonitorTimeout(
902 TimeDelta::FromMilliseconds(hung_renderer_delay_ms_
));
905 void RenderWidgetHostImpl::StopHangMonitorTimeout() {
906 time_when_considered_hung_
= Time();
907 RendererIsResponsive();
908 // We do not bother to stop the hung_renderer_timer_ here in case it will be
909 // started again shortly, which happens to be the common use case.
912 void RenderWidgetHostImpl::EnableFullAccessibilityMode() {
913 SetAccessibilityMode(AccessibilityModeComplete
);
916 static WebGestureEvent
MakeGestureEvent(WebInputEvent::Type type
,
917 double timestamp_seconds
,
921 WebGestureEvent result
;
926 result
.sourceDevice
= WebGestureEvent::Touchscreen
;
927 result
.timeStampSeconds
= timestamp_seconds
;
928 result
.modifiers
= modifiers
;
933 void RenderWidgetHostImpl::SimulateTouchGestureWithMouse(
934 const WebMouseEvent
& mouse_event
) {
935 int x
= mouse_event
.x
, y
= mouse_event
.y
;
936 float dx
= mouse_event
.movementX
, dy
= mouse_event
.movementY
;
937 static int startX
= 0, startY
= 0;
939 switch (mouse_event
.button
) {
940 case WebMouseEvent::ButtonLeft
:
941 if (mouse_event
.type
== WebInputEvent::MouseDown
) {
944 ForwardGestureEvent(MakeGestureEvent(
945 WebInputEvent::GestureScrollBegin
, mouse_event
.timeStampSeconds
,
948 if (dx
!= 0 || dy
!= 0) {
949 WebGestureEvent event
= MakeGestureEvent(
950 WebInputEvent::GestureScrollUpdate
, mouse_event
.timeStampSeconds
,
952 event
.data
.scrollUpdate
.deltaX
= dx
;
953 event
.data
.scrollUpdate
.deltaY
= dy
;
954 ForwardGestureEvent(event
);
956 if (mouse_event
.type
== WebInputEvent::MouseUp
) {
957 ForwardGestureEvent(MakeGestureEvent(
958 WebInputEvent::GestureScrollEnd
, mouse_event
.timeStampSeconds
,
962 case WebMouseEvent::ButtonMiddle
:
963 if (mouse_event
.type
== WebInputEvent::MouseDown
) {
966 ForwardGestureEvent(MakeGestureEvent(
967 WebInputEvent::GestureTapDown
, mouse_event
.timeStampSeconds
,
970 if (mouse_event
.type
== WebInputEvent::MouseUp
) {
971 ForwardGestureEvent(MakeGestureEvent(
972 WebInputEvent::GestureTap
, mouse_event
.timeStampSeconds
,
976 case WebMouseEvent::ButtonRight
:
977 if (mouse_event
.type
== WebInputEvent::MouseDown
) {
980 ForwardGestureEvent(MakeGestureEvent(
981 WebInputEvent::GesturePinchBegin
, mouse_event
.timeStampSeconds
,
984 if (dx
!= 0 || dy
!= 0) {
985 dx
= pow(dy
< 0 ? 0.998f
: 1.002f
, fabs(dy
));
986 WebGestureEvent event
= MakeGestureEvent(
987 WebInputEvent::GesturePinchUpdate
, mouse_event
.timeStampSeconds
,
989 event
.data
.pinchUpdate
.scale
= dx
;
990 ForwardGestureEvent(event
);
992 if (mouse_event
.type
== WebInputEvent::MouseUp
) {
993 ForwardGestureEvent(MakeGestureEvent(
994 WebInputEvent::GesturePinchEnd
, mouse_event
.timeStampSeconds
,
998 case WebMouseEvent::ButtonNone
:
1003 void RenderWidgetHostImpl::ForwardMouseEvent(const WebMouseEvent
& mouse_event
) {
1004 ForwardMouseEventWithLatencyInfo(
1005 MouseEventWithLatencyInfo(mouse_event
, NewInputLatencyInfo()));
1008 void RenderWidgetHostImpl::ForwardMouseEventWithLatencyInfo(
1009 const MouseEventWithLatencyInfo
& mouse_event
) {
1010 TRACE_EVENT2("input",
1011 "RenderWidgetHostImpl::ForwardMouseEventWithLatencyInfo",
1012 "x", mouse_event
.event
.x
, "y", mouse_event
.event
.y
);
1013 if (ignore_input_events_
|| process_
->IgnoreInputEvents())
1016 if (CommandLine::ForCurrentProcess()->HasSwitch(
1017 switches::kSimulateTouchScreenWithMouse
)) {
1018 SimulateTouchGestureWithMouse(mouse_event
.event
);
1022 if (mouse_event
.event
.type
== WebInputEvent::MouseDown
&&
1023 gesture_event_filter_
->GetTouchpadTapSuppressionController()->
1024 ShouldDeferMouseDown(mouse_event
))
1026 if (mouse_event
.event
.type
== WebInputEvent::MouseUp
&&
1027 gesture_event_filter_
->GetTouchpadTapSuppressionController()->
1028 ShouldSuppressMouseUp())
1031 ForwardMouseEventImmediately(mouse_event
);
1034 void RenderWidgetHostImpl::OnPointerEventActivate() {
1037 void RenderWidgetHostImpl::ForwardWheelEvent(
1038 const WebMouseWheelEvent
& wheel_event
) {
1039 ForwardWheelEventWithLatencyInfo(wheel_event
, NewInputLatencyInfo());
1042 void RenderWidgetHostImpl::ForwardWheelEventWithLatencyInfo(
1043 const WebMouseWheelEvent
& wheel_event
,
1044 const ui::LatencyInfo
& latency_info
) {
1045 TRACE_EVENT0("input",
1046 "RenderWidgetHostImpl::ForwardWheelEventWithLatencyInfo");
1047 if (ignore_input_events_
|| process_
->IgnoreInputEvents())
1050 if (delegate_
->PreHandleWheelEvent(wheel_event
))
1053 // If there's already a mouse wheel event waiting to be sent to the renderer,
1054 // add the new deltas to that event. Not doing so (e.g., by dropping the old
1055 // event, as for mouse moves) results in very slow scrolling on the Mac (on
1056 // which many, very small wheel events are sent).
1057 if (mouse_wheel_pending_
) {
1058 if (coalesced_mouse_wheel_events_
.empty() ||
1059 !ShouldCoalesceMouseWheelEvents(
1060 coalesced_mouse_wheel_events_
.back().event
, wheel_event
)) {
1061 coalesced_mouse_wheel_events_
.push_back(
1062 MouseWheelEventWithLatencyInfo(wheel_event
, latency_info
));
1064 MouseWheelEventWithLatencyInfo
* last_wheel_event
=
1065 &coalesced_mouse_wheel_events_
.back();
1066 float unaccelerated_x
=
1067 GetUnacceleratedDelta(last_wheel_event
->event
.deltaX
,
1068 last_wheel_event
->event
.accelerationRatioX
) +
1069 GetUnacceleratedDelta(wheel_event
.deltaX
,
1070 wheel_event
.accelerationRatioX
);
1071 float unaccelerated_y
=
1072 GetUnacceleratedDelta(last_wheel_event
->event
.deltaY
,
1073 last_wheel_event
->event
.accelerationRatioY
) +
1074 GetUnacceleratedDelta(wheel_event
.deltaY
,
1075 wheel_event
.accelerationRatioY
);
1076 last_wheel_event
->event
.deltaX
+= wheel_event
.deltaX
;
1077 last_wheel_event
->event
.deltaY
+= wheel_event
.deltaY
;
1078 last_wheel_event
->event
.wheelTicksX
+= wheel_event
.wheelTicksX
;
1079 last_wheel_event
->event
.wheelTicksY
+= wheel_event
.wheelTicksY
;
1080 last_wheel_event
->event
.accelerationRatioX
=
1081 GetAccelerationRatio(last_wheel_event
->event
.deltaX
, unaccelerated_x
);
1082 last_wheel_event
->event
.accelerationRatioY
=
1083 GetAccelerationRatio(last_wheel_event
->event
.deltaY
, unaccelerated_y
);
1084 DCHECK_GE(wheel_event
.timeStampSeconds
,
1085 last_wheel_event
->event
.timeStampSeconds
);
1086 last_wheel_event
->event
.timeStampSeconds
= wheel_event
.timeStampSeconds
;
1087 last_wheel_event
->latency
.MergeWith(latency_info
);
1091 mouse_wheel_pending_
= true;
1092 current_wheel_event_
= wheel_event
;
1094 HISTOGRAM_COUNTS_100("MPArch.RWH_WheelQueueSize",
1095 coalesced_mouse_wheel_events_
.size());
1097 ForwardInputEvent(wheel_event
, sizeof(WebMouseWheelEvent
), latency_info
,
1101 void RenderWidgetHostImpl::ForwardGestureEvent(
1102 const WebKit::WebGestureEvent
& gesture_event
) {
1103 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardGestureEvent");
1104 if (ignore_input_events_
|| process_
->IgnoreInputEvents())
1107 ui::LatencyInfo latency_info
= NewInputLatencyInfo();
1109 if (!IsInOverscrollGesture() &&
1110 !gesture_event_filter_
->ShouldForward(
1111 GestureEventWithLatencyInfo(gesture_event
, latency_info
))) {
1112 if (overscroll_controller_
.get())
1113 overscroll_controller_
->DiscardingGestureEvent(gesture_event
);
1117 ForwardInputEvent(gesture_event
, sizeof(WebGestureEvent
),
1118 latency_info
, false);
1121 // Forwards MouseEvent without passing it through
1122 // TouchpadTapSuppressionController.
1123 void RenderWidgetHostImpl::ForwardMouseEventImmediately(
1124 const MouseEventWithLatencyInfo
& mouse_event
) {
1125 TRACE_EVENT2("input",
1126 "RenderWidgetHostImpl::ForwardMouseEventImmediately",
1127 "x", mouse_event
.event
.x
, "y", mouse_event
.event
.y
);
1128 if (ignore_input_events_
|| process_
->IgnoreInputEvents())
1131 if (CommandLine::ForCurrentProcess()->HasSwitch(
1132 switches::kSimulateTouchScreenWithMouse
)) {
1133 SimulateTouchGestureWithMouse(mouse_event
.event
);
1137 // Avoid spamming the renderer with mouse move events. It is important
1138 // to note that WM_MOUSEMOVE events are anyways synthetic, but since our
1139 // thread is able to rapidly consume WM_MOUSEMOVE events, we may get way
1140 // more WM_MOUSEMOVE events than we wish to send to the renderer.
1141 if (mouse_event
.event
.type
== WebInputEvent::MouseMove
) {
1142 if (mouse_move_pending_
) {
1143 if (!next_mouse_move_
) {
1144 next_mouse_move_
.reset(new MouseEventWithLatencyInfo(mouse_event
));
1146 // Accumulate movement deltas.
1147 int x
= next_mouse_move_
->event
.movementX
;
1148 int y
= next_mouse_move_
->event
.movementY
;
1149 next_mouse_move_
->event
= mouse_event
.event
;
1150 next_mouse_move_
->event
.movementX
+= x
;
1151 next_mouse_move_
->event
.movementY
+= y
;
1152 next_mouse_move_
->latency
.MergeWith(mouse_event
.latency
);
1156 mouse_move_pending_
= true;
1157 } else if (mouse_event
.event
.type
== WebInputEvent::MouseDown
) {
1161 ForwardInputEvent(mouse_event
.event
, sizeof(WebMouseEvent
),
1162 mouse_event
.latency
, false);
1165 void RenderWidgetHostImpl::ForwardTouchEventImmediately(
1166 const TouchEventWithLatencyInfo
& touch_event
) {
1167 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardTouchEvent");
1168 if (ignore_input_events_
|| process_
->IgnoreInputEvents())
1171 ForwardInputEvent(touch_event
.event
, sizeof(WebKit::WebTouchEvent
),
1172 touch_event
.latency
, false);
1175 void RenderWidgetHostImpl::ForwardGestureEventImmediately(
1176 const GestureEventWithLatencyInfo
& gesture_event
) {
1177 if (ignore_input_events_
|| process_
->IgnoreInputEvents())
1179 ForwardInputEvent(gesture_event
.event
, sizeof(WebGestureEvent
),
1180 gesture_event
.latency
, false);
1183 void RenderWidgetHostImpl::ForwardKeyboardEvent(
1184 const NativeWebKeyboardEvent
& key_event
) {
1185 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardKeyboardEvent");
1186 if (ignore_input_events_
|| process_
->IgnoreInputEvents())
1189 // First, let keypress listeners take a shot at handling the event. If a
1190 // listener handles the event, it should not be propagated to the renderer.
1191 if (KeyPressListenersHandleEvent(key_event
)) {
1192 // Some keypresses that are accepted by the listener might have follow up
1193 // char events, which should be ignored.
1194 if (key_event
.type
== WebKeyboardEvent::RawKeyDown
)
1195 suppress_next_char_events_
= true;
1199 if (key_event
.type
== WebKeyboardEvent::Char
&&
1200 (key_event
.windowsKeyCode
== ui::VKEY_RETURN
||
1201 key_event
.windowsKeyCode
== ui::VKEY_SPACE
)) {
1205 // Double check the type to make sure caller hasn't sent us nonsense that
1206 // will mess up our key queue.
1207 if (WebInputEvent::isKeyboardEventType(key_event
.type
)) {
1208 if (suppress_next_char_events_
) {
1209 // If preceding RawKeyDown event was handled by the browser, then we need
1210 // suppress all Char events generated by it. Please note that, one
1211 // RawKeyDown event may generate multiple Char events, so we can't reset
1212 // |suppress_next_char_events_| until we get a KeyUp or a RawKeyDown.
1213 if (key_event
.type
== WebKeyboardEvent::Char
)
1215 // We get a KeyUp or a RawKeyDown event.
1216 suppress_next_char_events_
= false;
1219 bool is_keyboard_shortcut
= false;
1220 // Only pre-handle the key event if it's not handled by the input method.
1221 if (delegate_
&& !key_event
.skip_in_browser
) {
1222 // We need to set |suppress_next_char_events_| to true if
1223 // PreHandleKeyboardEvent() returns true, but |this| may already be
1224 // destroyed at that time. So set |suppress_next_char_events_| true here,
1225 // then revert it afterwards when necessary.
1226 if (key_event
.type
== WebKeyboardEvent::RawKeyDown
)
1227 suppress_next_char_events_
= true;
1229 // Tab switching/closing accelerators aren't sent to the renderer to avoid
1230 // a hung/malicious renderer from interfering.
1231 if (delegate_
->PreHandleKeyboardEvent(key_event
, &is_keyboard_shortcut
))
1234 if (key_event
.type
== WebKeyboardEvent::RawKeyDown
)
1235 suppress_next_char_events_
= false;
1238 // Don't add this key to the queue if we have no way to send the message...
1239 if (!process_
->HasConnection())
1242 // Put all WebKeyboardEvent objects in a queue since we can't trust the
1243 // renderer and we need to give something to the HandleKeyboardEvent
1245 key_queue_
.push_back(key_event
);
1246 HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_
.size());
1248 gesture_event_filter_
->FlingHasBeenHalted();
1250 // Only forward the non-native portions of our event.
1251 ForwardInputEvent(key_event
, sizeof(WebKeyboardEvent
),
1252 NewInputLatencyInfo(),
1253 is_keyboard_shortcut
);
1257 void RenderWidgetHostImpl::SendCursorVisibilityState(bool is_visible
) {
1258 Send(new InputMsg_CursorVisibilityChange(GetRoutingID(), is_visible
));
1261 int64
RenderWidgetHostImpl::GetLatencyComponentId() {
1262 return GetRoutingID() | (static_cast<int64
>(GetProcess()->GetID()) << 32);
1266 void RenderWidgetHostImpl::DisableResizeAckCheckForTesting() {
1267 g_check_for_pending_resize_ack
= false;
1270 ui::LatencyInfo
RenderWidgetHostImpl::NewInputLatencyInfo() {
1271 ui::LatencyInfo info
;
1272 info
.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_RWH_COMPONENT
,
1273 GetLatencyComponentId(),
1274 ++last_input_number_
);
1278 void RenderWidgetHostImpl::SendInputEvent(const WebInputEvent
& input_event
,
1280 const ui::LatencyInfo
& latency_info
,
1281 bool is_keyboard_shortcut
) {
1282 input_event_start_time_
= TimeTicks::Now();
1283 Send(new InputMsg_HandleInputEvent(
1284 routing_id_
, &input_event
, latency_info
, is_keyboard_shortcut
));
1285 increment_in_flight_event_count();
1288 void RenderWidgetHostImpl::ForwardInputEvent(
1289 const WebInputEvent
& input_event
, int event_size
,
1290 const ui::LatencyInfo
& latency_info
, bool is_keyboard_shortcut
) {
1291 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardInputEvent");
1293 if (!process_
->HasConnection())
1296 DCHECK(!process_
->IgnoreInputEvents());
1298 if (overscroll_controller_
.get() &&
1299 !overscroll_controller_
->WillDispatchEvent(input_event
, latency_info
)) {
1300 if (input_event
.type
== WebKit::WebInputEvent::MouseMove
) {
1301 // Since this mouse-move event has been consumed, there will be no ACKs.
1302 // So reset the state here so that future mouse-move events do reach the
1304 mouse_move_pending_
= false;
1305 } else if (input_event
.type
== WebKit::WebInputEvent::MouseWheel
) {
1306 // Reset the wheel-event state when appropriate.
1307 mouse_wheel_pending_
= false;
1308 } else if (WebInputEvent::isGestureEventType(input_event
.type
) &&
1309 gesture_event_filter_
->HasQueuedGestureEvents()) {
1310 // If the gesture-event filter has queued gesture events, that implies it
1311 // is awaiting an ack for the event. Since the event is being consumed by
1312 // the over scroll here, it is never sent to the renderer, and so it won't
1313 // receive any ACKs. So send the ACK to the gesture event filter
1314 // immediately, and mark it as having been processed.
1315 gesture_event_filter_
->ProcessGestureAck(true, input_event
.type
);
1316 } else if (WebInputEvent::isTouchEventType(input_event
.type
)) {
1317 // During an overscroll gesture initiated by touch-scrolling, the
1318 // touch-events do not reset or contribute to the overscroll gesture.
1319 // However, the touch-events are not sent to the renderer. So send and ACK
1320 // to the touch-event queue immediately. Mark the event as not processed,
1321 // to make sure that the touch-scroll gesture that initiated the
1322 // overscroll is updated properly.
1323 touch_event_queue_
->ProcessTouchAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED
);
1328 // Transmit any pending wheel events on a non-wheel event. This ensures that
1329 // the renderer receives the final PhaseEnded wheel event, which is necessary
1330 // to terminate rubber-banding, for example.
1331 if (input_event
.type
!= WebInputEvent::MouseWheel
) {
1332 for (size_t i
= 0; i
< coalesced_mouse_wheel_events_
.size(); ++i
) {
1333 SendInputEvent(coalesced_mouse_wheel_events_
[i
].event
,
1334 sizeof(WebMouseWheelEvent
),
1335 coalesced_mouse_wheel_events_
[i
].latency
,
1338 coalesced_mouse_wheel_events_
.clear();
1342 // Perform optional, synchronous event handling, sending ACK messages for
1343 // processed events, or proceeding as usual.
1344 InputEventAckState filter_ack
= view_
->FilterInputEvent(input_event
);
1345 switch (filter_ack
) {
1346 // Send the ACK and early exit.
1347 case INPUT_EVENT_ACK_STATE_CONSUMED
:
1348 case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS
:
1349 next_mouse_move_
.reset();
1350 OnInputEventAck(input_event
.type
, filter_ack
);
1351 // WARNING: |this| may be deleted at this point.
1354 // Proceed as normal.
1355 case INPUT_EVENT_ACK_STATE_UNKNOWN
:
1356 case INPUT_EVENT_ACK_STATE_NOT_CONSUMED
:
1362 SendInputEvent(input_event
, event_size
, latency_info
, is_keyboard_shortcut
);
1364 // Any input event cancels a pending mouse move event. Note that
1365 // |next_mouse_move_| possibly owns |input_event|, so don't use |input_event|
1367 next_mouse_move_
.reset();
1369 StartHangMonitorTimeout(
1370 TimeDelta::FromMilliseconds(hung_renderer_delay_ms_
));
1373 void RenderWidgetHostImpl::ForwardTouchEventWithLatencyInfo(
1374 const WebKit::WebTouchEvent
& touch_event
,
1375 const ui::LatencyInfo
& ui_latency
) {
1376 ui::LatencyInfo latency_info
= NewInputLatencyInfo();
1377 latency_info
.MergeWith(ui_latency
);
1378 TouchEventWithLatencyInfo
touch_with_latency(touch_event
, latency_info
);
1379 touch_event_queue_
->QueueEvent(touch_with_latency
);
1382 void RenderWidgetHostImpl::AddKeyboardListener(KeyboardListener
* listener
) {
1383 keyboard_listeners_
.AddObserver(listener
);
1386 void RenderWidgetHostImpl::RemoveKeyboardListener(
1387 KeyboardListener
* listener
) {
1388 // Ensure that the element is actually an observer.
1389 DCHECK(keyboard_listeners_
.HasObserver(listener
));
1390 keyboard_listeners_
.RemoveObserver(listener
);
1393 void RenderWidgetHostImpl::GetWebScreenInfo(WebKit::WebScreenInfo
* result
) {
1394 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::GetWebScreenInfo");
1396 static_cast<RenderWidgetHostViewPort
*>(GetView())->GetScreenInfo(result
);
1398 RenderWidgetHostViewPort::GetDefaultScreenInfo(result
);
1401 const NativeWebKeyboardEvent
*
1402 RenderWidgetHostImpl::GetLastKeyboardEvent() const {
1403 if (key_queue_
.empty())
1405 return &key_queue_
.front();
1408 void RenderWidgetHostImpl::NotifyScreenInfoChanged() {
1409 // The resize message (which may not happen immediately) will carry with it
1410 // the screen info as well as the new size (if the screen has changed scale
1412 screen_info_
.reset();
1413 screen_info_out_of_date_
= true;
1417 void RenderWidgetHostImpl::GetSnapshotFromRenderer(
1418 const gfx::Rect
& src_subrect
,
1419 const base::Callback
<void(bool, const SkBitmap
&)>& callback
) {
1420 TRACE_EVENT0("browser", "RenderWidgetHostImpl::GetSnapshotFromRenderer");
1421 pending_snapshots_
.push(callback
);
1423 gfx::Rect copy_rect
= src_subrect
.IsEmpty() ?
1424 gfx::Rect(view_
->GetViewBounds().size()) : src_subrect
;
1426 gfx::Rect copy_rect_in_pixel
= ConvertViewRectToPixel(view_
, copy_rect
);
1427 Send(new ViewMsg_Snapshot(GetRoutingID(), copy_rect_in_pixel
));
1430 void RenderWidgetHostImpl::OnSnapshot(bool success
,
1431 const SkBitmap
& bitmap
) {
1432 if (pending_snapshots_
.size() == 0) {
1433 LOG(ERROR
) << "RenderWidgetHostImpl::OnSnapshot: "
1434 "Received a snapshot that was not requested.";
1438 base::Callback
<void(bool, const SkBitmap
&)> callback
=
1439 pending_snapshots_
.front();
1440 pending_snapshots_
.pop();
1443 callback
.Run(success
, SkBitmap());
1447 callback
.Run(success
, bitmap
);
1450 void RenderWidgetHostImpl::UpdateVSyncParameters(base::TimeTicks timebase
,
1451 base::TimeDelta interval
) {
1452 Send(new ViewMsg_UpdateVSyncParameters(GetRoutingID(), timebase
, interval
));
1455 void RenderWidgetHostImpl::RendererExited(base::TerminationStatus status
,
1457 // Clearing this flag causes us to re-create the renderer when recovering
1458 // from a crashed renderer.
1459 renderer_initialized_
= false;
1461 waiting_for_screen_rects_ack_
= false;
1463 // Must reset these to ensure that mouse move/wheel events work with a new
1465 mouse_move_pending_
= false;
1466 next_mouse_move_
.reset();
1467 mouse_wheel_pending_
= false;
1468 coalesced_mouse_wheel_events_
.clear();
1470 // Must reset these to ensure that SelectRange works with a new renderer.
1471 select_range_pending_
= false;
1472 next_selection_range_
.reset();
1474 // Must reset these to ensure that MoveCaret works with a new renderer.
1475 move_caret_pending_
= false;
1476 next_move_caret_
.reset();
1478 touch_event_queue_
->Reset();
1480 // Must reset these to ensure that gesture events work with a new renderer.
1481 gesture_event_filter_
->Reset();
1483 if (overscroll_controller_
)
1484 overscroll_controller_
->Reset();
1486 // Must reset these to ensure that keyboard events work with a new renderer.
1488 suppress_next_char_events_
= false;
1490 // Reset some fields in preparation for recovering from a crash.
1491 ResetSizeAndRepaintPendingFlags();
1492 current_size_
.SetSize(0, 0);
1494 is_accelerated_compositing_active_
= false;
1496 // Reset this to ensure the hung renderer mechanism is working properly.
1497 in_flight_event_count_
= 0;
1500 GpuSurfaceTracker::Get()->SetSurfaceHandle(surface_id_
,
1501 gfx::GLSurfaceHandle());
1502 view_
->RenderViewGone(status
, exit_code
);
1503 view_
= NULL
; // The View should be deleted by RenderViewGone.
1506 BackingStoreManager::RemoveBackingStore(this);
1509 void RenderWidgetHostImpl::UpdateTextDirection(WebTextDirection direction
) {
1510 text_direction_updated_
= true;
1511 text_direction_
= direction
;
1514 void RenderWidgetHostImpl::CancelUpdateTextDirection() {
1515 if (text_direction_updated_
)
1516 text_direction_canceled_
= true;
1519 void RenderWidgetHostImpl::NotifyTextDirection() {
1520 if (text_direction_updated_
) {
1521 if (!text_direction_canceled_
)
1522 Send(new ViewMsg_SetTextDirection(GetRoutingID(), text_direction_
));
1523 text_direction_updated_
= false;
1524 text_direction_canceled_
= false;
1528 void RenderWidgetHostImpl::SetInputMethodActive(bool activate
) {
1529 input_method_active_
= activate
;
1530 Send(new ViewMsg_SetInputMethodActive(GetRoutingID(), activate
));
1533 void RenderWidgetHostImpl::ImeSetComposition(
1534 const string16
& text
,
1535 const std::vector
<WebKit::WebCompositionUnderline
>& underlines
,
1536 int selection_start
,
1537 int selection_end
) {
1538 Send(new ViewMsg_ImeSetComposition(
1539 GetRoutingID(), text
, underlines
, selection_start
, selection_end
));
1542 void RenderWidgetHostImpl::ImeConfirmComposition(const string16
& text
) {
1543 ImeConfirmComposition(text
, ui::Range::InvalidRange());
1546 void RenderWidgetHostImpl::ImeConfirmComposition(
1547 const string16
& text
, const ui::Range
& replacement_range
) {
1548 Send(new ViewMsg_ImeConfirmComposition(
1549 GetRoutingID(), text
, replacement_range
));
1552 void RenderWidgetHostImpl::ImeConfirmComposition() {
1553 ImeConfirmComposition(string16());
1556 void RenderWidgetHostImpl::ImeCancelComposition() {
1557 Send(new ViewMsg_ImeSetComposition(GetRoutingID(), string16(),
1558 std::vector
<WebKit::WebCompositionUnderline
>(), 0, 0));
1561 void RenderWidgetHostImpl::ExtendSelectionAndDelete(
1564 Send(new ViewMsg_ExtendSelectionAndDelete(GetRoutingID(), before
, after
));
1567 gfx::Rect
RenderWidgetHostImpl::GetRootWindowResizerRect() const {
1571 void RenderWidgetHostImpl::RequestToLockMouse(bool user_gesture
,
1572 bool last_unlocked_by_target
) {
1573 // Directly reject to lock the mouse. Subclass can override this method to
1574 // decide whether to allow mouse lock or not.
1575 GotResponseToLockMouseRequest(false);
1578 void RenderWidgetHostImpl::RejectMouseLockOrUnlockIfNecessary() {
1579 DCHECK(!pending_mouse_lock_request_
|| !IsMouseLocked());
1580 if (pending_mouse_lock_request_
) {
1581 pending_mouse_lock_request_
= false;
1582 Send(new ViewMsg_LockMouse_ACK(routing_id_
, false));
1583 } else if (IsMouseLocked()) {
1584 view_
->UnlockMouse();
1588 bool RenderWidgetHostImpl::IsMouseLocked() const {
1589 return view_
? view_
->IsMouseLocked() : false;
1592 bool RenderWidgetHostImpl::IsFullscreen() const {
1596 void RenderWidgetHostImpl::SetShouldAutoResize(bool enable
) {
1597 should_auto_resize_
= enable
;
1600 bool RenderWidgetHostImpl::IsInOverscrollGesture() const {
1601 return overscroll_controller_
.get() &&
1602 overscroll_controller_
->overscroll_mode() != OVERSCROLL_NONE
;
1605 void RenderWidgetHostImpl::Destroy() {
1606 NotificationService::current()->Notify(
1607 NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED
,
1608 Source
<RenderWidgetHost
>(this),
1609 NotificationService::NoDetails());
1611 // Tell the view to die.
1612 // Note that in the process of the view shutting down, it can call a ton
1613 // of other messages on us. So if you do any other deinitialization here,
1614 // do it after this call to view_->Destroy().
1621 void RenderWidgetHostImpl::CheckRendererIsUnresponsive() {
1622 // If we received a call to StopHangMonitorTimeout.
1623 if (time_when_considered_hung_
.is_null())
1626 // If we have not waited long enough, then wait some more.
1627 Time now
= Time::Now();
1628 if (now
< time_when_considered_hung_
) {
1629 StartHangMonitorTimeout(time_when_considered_hung_
- now
);
1633 // OK, looks like we have a hung renderer!
1634 NotificationService::current()->Notify(
1635 NOTIFICATION_RENDERER_PROCESS_HANG
,
1636 Source
<RenderWidgetHost
>(this),
1637 NotificationService::NoDetails());
1638 is_unresponsive_
= true;
1639 NotifyRendererUnresponsive();
1642 void RenderWidgetHostImpl::RendererIsResponsive() {
1643 if (is_unresponsive_
) {
1644 is_unresponsive_
= false;
1645 NotifyRendererResponsive();
1649 void RenderWidgetHostImpl::OnRenderViewReady() {
1654 void RenderWidgetHostImpl::OnRenderViewGone(int status
, int exit_code
) {
1655 // TODO(evanm): This synchronously ends up calling "delete this".
1656 // Is that really what we want in response to this message? I'm matching
1657 // previous behavior of the code here.
1661 void RenderWidgetHostImpl::OnClose() {
1665 void RenderWidgetHostImpl::OnSetTooltipText(
1666 const string16
& tooltip_text
,
1667 WebTextDirection text_direction_hint
) {
1668 // First, add directionality marks around tooltip text if necessary.
1669 // A naive solution would be to simply always wrap the text. However, on
1670 // windows, Unicode directional embedding characters can't be displayed on
1671 // systems that lack RTL fonts and are instead displayed as empty squares.
1673 // To get around this we only wrap the string when we deem it necessary i.e.
1674 // when the locale direction is different than the tooltip direction hint.
1676 // Currently, we use element's directionality as the tooltip direction hint.
1677 // An alternate solution would be to set the overall directionality based on
1678 // trying to detect the directionality from the tooltip text rather than the
1679 // element direction. One could argue that would be a preferable solution
1680 // but we use the current approach to match Fx & IE's behavior.
1681 string16 wrapped_tooltip_text
= tooltip_text
;
1682 if (!tooltip_text
.empty()) {
1683 if (text_direction_hint
== WebKit::WebTextDirectionLeftToRight
) {
1684 // Force the tooltip to have LTR directionality.
1685 wrapped_tooltip_text
=
1686 base::i18n::GetDisplayStringInLTRDirectionality(wrapped_tooltip_text
);
1687 } else if (text_direction_hint
== WebKit::WebTextDirectionRightToLeft
&&
1688 !base::i18n::IsRTL()) {
1689 // Force the tooltip to have RTL directionality.
1690 base::i18n::WrapStringWithRTLFormatting(&wrapped_tooltip_text
);
1694 view_
->SetTooltipText(wrapped_tooltip_text
);
1697 void RenderWidgetHostImpl::OnUpdateScreenRectsAck() {
1698 waiting_for_screen_rects_ack_
= false;
1702 if (view_
->GetViewBounds() == last_view_screen_rect_
&&
1703 view_
->GetBoundsInRootWindow() == last_window_screen_rect_
) {
1710 void RenderWidgetHostImpl::OnRequestMove(const gfx::Rect
& pos
) {
1711 // Note that we ignore the position.
1713 view_
->SetBounds(pos
);
1714 Send(new ViewMsg_Move_ACK(routing_id_
));
1718 void RenderWidgetHostImpl::OnPaintAtSizeAck(int tag
, const gfx::Size
& size
) {
1719 std::pair
<int, gfx::Size
> details
= std::make_pair(tag
, size
);
1720 NotificationService::current()->Notify(
1721 NOTIFICATION_RENDER_WIDGET_HOST_DID_RECEIVE_PAINT_AT_SIZE_ACK
,
1722 Source
<RenderWidgetHost
>(this),
1723 Details
<std::pair
<int, gfx::Size
> >(&details
));
1726 void RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwapped(
1727 const ViewHostMsg_CompositorSurfaceBuffersSwapped_Params
& params
) {
1728 TRACE_EVENT0("renderer_host",
1729 "RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwapped");
1731 AcceleratedSurfaceMsg_BufferPresented_Params ack_params
;
1732 ack_params
.sync_point
= 0;
1733 RenderWidgetHostImpl::AcknowledgeBufferPresent(params
.route_id
,
1734 params
.gpu_process_host_id
,
1738 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params gpu_params
;
1739 gpu_params
.surface_id
= params
.surface_id
;
1740 gpu_params
.surface_handle
= params
.surface_handle
;
1741 gpu_params
.route_id
= params
.route_id
;
1742 gpu_params
.size
= params
.size
;
1743 gpu_params
.scale_factor
= params
.scale_factor
;
1744 gpu_params
.latency_info
= params
.latency_info
;
1745 view_
->AcceleratedSurfaceBuffersSwapped(gpu_params
,
1746 params
.gpu_process_host_id
);
1749 bool RenderWidgetHostImpl::OnSwapCompositorFrame(
1750 const IPC::Message
& message
) {
1751 ViewHostMsg_SwapCompositorFrame::Param param
;
1752 if (!ViewHostMsg_SwapCompositorFrame::Read(&message
, ¶m
))
1754 scoped_ptr
<cc::CompositorFrame
> frame(new cc::CompositorFrame
);
1755 param
.a
.AssignTo(frame
.get());
1758 view_
->OnSwapCompositorFrame(frame
.Pass());
1760 cc::CompositorFrameAck ack
;
1761 if (frame
->gl_frame_data
) {
1762 ack
.gl_frame_data
= frame
->gl_frame_data
.Pass();
1763 ack
.gl_frame_data
->sync_point
= 0;
1764 } else if (frame
->delegated_frame_data
) {
1765 ack
.resources
.swap(frame
->delegated_frame_data
->resource_list
);
1766 } else if (frame
->software_frame_data
) {
1767 ack
.last_software_frame_id
= frame
->software_frame_data
->id
;
1769 SendSwapCompositorFrameAck(routing_id_
, process_
->GetID(), ack
);
1774 void RenderWidgetHostImpl::OnOverscrolled(
1775 gfx::Vector2dF accumulated_overscroll
,
1776 gfx::Vector2dF current_fling_velocity
) {
1778 view_
->OnOverscrolled(accumulated_overscroll
, current_fling_velocity
);
1781 void RenderWidgetHostImpl::OnUpdateRect(
1782 const ViewHostMsg_UpdateRect_Params
& params
) {
1783 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::OnUpdateRect");
1784 TimeTicks paint_start
= TimeTicks::Now();
1786 // Update our knowledge of the RenderWidget's size.
1787 current_size_
= params
.view_size
;
1788 // Update our knowledge of the RenderWidget's scroll offset.
1789 last_scroll_offset_
= params
.scroll_offset
;
1791 bool is_resize_ack
=
1792 ViewHostMsg_UpdateRect_Flags::is_resize_ack(params
.flags
);
1794 // resize_ack_pending_ needs to be cleared before we call DidPaintRect, since
1795 // that will end up reaching GetBackingStore.
1796 if (is_resize_ack
) {
1797 DCHECK(!g_check_for_pending_resize_ack
|| resize_ack_pending_
);
1798 resize_ack_pending_
= false;
1799 in_flight_size_
.SetSize(0, 0);
1802 bool is_repaint_ack
=
1803 ViewHostMsg_UpdateRect_Flags::is_repaint_ack(params
.flags
);
1804 if (is_repaint_ack
) {
1805 DCHECK(repaint_ack_pending_
);
1806 TRACE_EVENT_ASYNC_END0(
1807 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
1808 repaint_ack_pending_
= false;
1809 TimeDelta delta
= TimeTicks::Now() - repaint_start_time_
;
1810 UMA_HISTOGRAM_TIMES("MPArch.RWH_RepaintDelta", delta
);
1813 DCHECK(!params
.view_size
.IsEmpty());
1815 bool was_async
= false;
1817 // If this is a GPU UpdateRect, params.bitmap is invalid and dib will be NULL.
1818 TransportDIB
* dib
= process_
->GetTransportDIB(params
.bitmap
);
1820 // If gpu process does painting, scroll_rect and copy_rects are always empty
1821 // and backing store is never used.
1823 DCHECK(!params
.bitmap_rect
.IsEmpty());
1824 gfx::Size pixel_size
= gfx::ToFlooredSize(
1825 gfx::ScaleSize(params
.bitmap_rect
.size(), params
.scale_factor
));
1826 const size_t size
= pixel_size
.height() * pixel_size
.width() * 4;
1827 if (dib
->size() < size
) {
1828 DLOG(WARNING
) << "Transport DIB too small for given rectangle";
1829 RecordAction(UserMetricsAction("BadMessageTerminate_RWH1"));
1830 GetProcess()->ReceivedBadMessage();
1832 UNSHIPPED_TRACE_EVENT_INSTANT2("test_latency", "UpdateRect",
1833 TRACE_EVENT_SCOPE_THREAD
,
1834 "x+y", params
.bitmap_rect
.x() + params
.bitmap_rect
.y(),
1835 "color", 0xffffff & *static_cast<uint32
*>(dib
->memory()));
1836 UNSHIPPED_TRACE_EVENT_INSTANT1("test_latency", "UpdateRectWidth",
1837 TRACE_EVENT_SCOPE_THREAD
,
1838 "width", params
.bitmap_rect
.width());
1840 // Scroll the backing store.
1841 if (!params
.scroll_rect
.IsEmpty()) {
1842 ScrollBackingStoreRect(params
.scroll_delta
,
1847 // Paint the backing store. This will update it with the
1848 // renderer-supplied bits. The view will read out of the backing store
1849 // later to actually draw to the screen.
1850 was_async
= PaintBackingStoreRect(
1855 params
.scale_factor
,
1856 base::Bind(&RenderWidgetHostImpl::DidUpdateBackingStore
,
1857 weak_factory_
.GetWeakPtr(), params
, paint_start
));
1862 DidUpdateBackingStore(params
, paint_start
);
1865 if (should_auto_resize_
) {
1866 bool post_callback
= new_auto_size_
.IsEmpty();
1867 new_auto_size_
= params
.view_size
;
1868 if (post_callback
) {
1869 base::MessageLoop::current()->PostTask(
1871 base::Bind(&RenderWidgetHostImpl::DelayedAutoResized
,
1872 weak_factory_
.GetWeakPtr()));
1876 // Log the time delta for processing a paint message. On platforms that don't
1877 // support asynchronous painting, this is equivalent to
1878 // MPArch.RWH_TotalPaintTime.
1879 TimeDelta delta
= TimeTicks::Now() - paint_start
;
1880 UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgUpdateRect", delta
);
1883 void RenderWidgetHostImpl::OnUpdateIsDelayed() {
1884 if (in_get_backing_store_
)
1885 abort_get_backing_store_
= true;
1888 void RenderWidgetHostImpl::DidUpdateBackingStore(
1889 const ViewHostMsg_UpdateRect_Params
& params
,
1890 const TimeTicks
& paint_start
) {
1891 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::DidUpdateBackingStore");
1892 TimeTicks update_start
= TimeTicks::Now();
1894 if (params
.needs_ack
) {
1895 // ACK early so we can prefetch the next PaintRect if there is a next one.
1896 // This must be done AFTER we're done painting with the bitmap supplied by
1897 // the renderer. This ACK is a signal to the renderer that the backing store
1898 // can be re-used, so the bitmap may be invalid after this call.
1899 Send(new ViewMsg_UpdateRect_ACK(routing_id_
));
1902 // Move the plugins if the view hasn't already been destroyed. Plugin moves
1903 // will not be re-issued, so must move them now, regardless of whether we
1904 // paint or not. MovePluginWindows attempts to move the plugin windows and
1905 // in the process could dispatch other window messages which could cause the
1906 // view to be destroyed.
1908 view_
->MovePluginWindows(params
.scroll_offset
, params
.plugin_window_moves
);
1910 NotificationService::current()->Notify(
1911 NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE
,
1912 Source
<RenderWidgetHost
>(this),
1913 NotificationService::NoDetails());
1915 // We don't need to update the view if the view is hidden. We must do this
1916 // early return after the ACK is sent, however, or the renderer will not send
1921 // Now paint the view. Watch out: it might be destroyed already.
1922 if (view_
&& !is_accelerated_compositing_active_
) {
1923 view_being_painted_
= true;
1924 view_
->DidUpdateBackingStore(params
.scroll_rect
, params
.scroll_delta
,
1925 params
.copy_rects
, params
.latency_info
);
1926 view_being_painted_
= false;
1929 // If we got a resize ack, then perhaps we have another resize to send?
1930 bool is_resize_ack
=
1931 ViewHostMsg_UpdateRect_Flags::is_resize_ack(params
.flags
);
1935 // Log the time delta for processing a paint message.
1936 TimeTicks now
= TimeTicks::Now();
1937 TimeDelta delta
= now
- update_start
;
1938 UMA_HISTOGRAM_TIMES("MPArch.RWH_DidUpdateBackingStore", delta
);
1940 // Measures the time from receiving the MsgUpdateRect IPC to completing the
1941 // DidUpdateBackingStore() method. On platforms which have asynchronous
1942 // painting, such as Linux, this is the sum of MPArch.RWH_OnMsgUpdateRect,
1943 // MPArch.RWH_DidUpdateBackingStore, and the time spent asynchronously
1944 // waiting for the paint to complete.
1946 // On other platforms, this will be equivalent to MPArch.RWH_OnMsgUpdateRect.
1947 delta
= now
- paint_start
;
1948 UMA_HISTOGRAM_TIMES("MPArch.RWH_TotalPaintTime", delta
);
1949 UNSHIPPED_TRACE_EVENT_INSTANT1("test_latency", "UpdateRectComplete",
1950 TRACE_EVENT_SCOPE_THREAD
,
1951 "x+y", params
.bitmap_rect
.x() + params
.bitmap_rect
.y());
1954 void RenderWidgetHostImpl::OnInputEventAck(
1955 WebInputEvent::Type event_type
, InputEventAckState ack_result
) {
1956 TRACE_EVENT0("input", "RenderWidgetHostImpl::OnInputEventAck");
1957 bool processed
= (ack_result
== INPUT_EVENT_ACK_STATE_CONSUMED
);
1959 // Log the time delta for processing an input event.
1960 TimeDelta delta
= TimeTicks::Now() - input_event_start_time_
;
1961 UMA_HISTOGRAM_TIMES("MPArch.RWH_InputEventDelta", delta
);
1963 // Cancel pending hung renderer checks since the renderer is responsive.
1964 if (decrement_in_flight_event_count() == 0)
1965 StopHangMonitorTimeout();
1967 int type
= static_cast<int>(event_type
);
1968 if (type
< WebInputEvent::Undefined
) {
1969 RecordAction(UserMetricsAction("BadMessageTerminate_RWH2"));
1970 process_
->ReceivedBadMessage();
1971 } else if (type
== WebInputEvent::MouseMove
) {
1972 mouse_move_pending_
= false;
1974 // now, we can send the next mouse move event
1975 if (next_mouse_move_
) {
1976 DCHECK(next_mouse_move_
->event
.type
== WebInputEvent::MouseMove
);
1977 ForwardMouseEventWithLatencyInfo(*next_mouse_move_
);
1979 } else if (WebInputEvent::isKeyboardEventType(type
)) {
1980 ProcessKeyboardEventAck(type
, processed
);
1981 } else if (type
== WebInputEvent::MouseWheel
) {
1982 ProcessWheelAck(processed
);
1983 } else if (WebInputEvent::isTouchEventType(type
)) {
1984 ProcessTouchAck(ack_result
);
1985 } else if (WebInputEvent::isGestureEventType(type
)) {
1986 ProcessGestureAck(processed
, type
);
1989 // WARNING: |this| may be deleted at this point.
1991 // This is used only for testing, and the other end does not use the
1992 // source object. On linux, specifying
1993 // Source<RenderWidgetHost> results in a very strange
1994 // runtime error in the epilogue of the enclosing
1995 // (OnInputEventAck) method, but not on other platforms; using
1996 // 'void' instead is just as safe (since NotificationSource
1997 // is not actually typesafe) and avoids this error.
1998 NotificationService::current()->Notify(
1999 NOTIFICATION_RENDER_WIDGET_HOST_DID_RECEIVE_INPUT_EVENT_ACK
,
2001 Details
<int>(&type
));
2004 void RenderWidgetHostImpl::OnBeginSmoothScroll(
2005 const ViewHostMsg_BeginSmoothScroll_Params
& params
) {
2008 smooth_scroll_gesture_controller_
.BeginSmoothScroll(view_
, params
);
2011 void RenderWidgetHostImpl::OnSelectRangeAck() {
2012 select_range_pending_
= false;
2013 if (next_selection_range_
) {
2014 scoped_ptr
<SelectionRange
> next(next_selection_range_
.Pass());
2015 SelectRange(next
->start
, next
->end
);
2019 void RenderWidgetHostImpl::OnMsgMoveCaretAck() {
2020 move_caret_pending_
= false;
2021 if (next_move_caret_
) {
2022 scoped_ptr
<gfx::Point
> next(next_move_caret_
.Pass());
2027 void RenderWidgetHostImpl::ProcessWheelAck(bool processed
) {
2028 mouse_wheel_pending_
= false;
2030 if (overscroll_controller_
)
2031 overscroll_controller_
->ReceivedEventACK(current_wheel_event_
, processed
);
2033 // Process the unhandled wheel event here before calling
2034 // ForwardWheelEventWithLatencyInfo() since it will mutate
2035 // current_wheel_event_.
2036 if (!processed
&& !is_hidden_
&& view_
)
2037 view_
->UnhandledWheelEvent(current_wheel_event_
);
2039 // Now send the next (coalesced) mouse wheel event.
2040 if (!coalesced_mouse_wheel_events_
.empty()) {
2041 MouseWheelEventWithLatencyInfo next_wheel_event
=
2042 coalesced_mouse_wheel_events_
.front();
2043 coalesced_mouse_wheel_events_
.pop_front();
2044 ForwardWheelEventWithLatencyInfo(next_wheel_event
.event
,
2045 next_wheel_event
.latency
);
2049 void RenderWidgetHostImpl::ProcessGestureAck(bool processed
, int type
) {
2050 if (overscroll_controller_
) {
2051 overscroll_controller_
->ReceivedEventACK(
2052 gesture_event_filter_
->GetGestureEventAwaitingAck(), processed
);
2054 gesture_event_filter_
->ProcessGestureAck(processed
, type
);
2057 view_
->GestureEventAck(type
);
2060 void RenderWidgetHostImpl::ProcessTouchAck(InputEventAckState ack_result
) {
2061 touch_event_queue_
->ProcessTouchAck(ack_result
);
2064 void RenderWidgetHostImpl::OnFocus() {
2065 // Only RenderViewHost can deal with that message.
2066 RecordAction(UserMetricsAction("BadMessageTerminate_RWH4"));
2067 GetProcess()->ReceivedBadMessage();
2070 void RenderWidgetHostImpl::OnBlur() {
2071 // Only RenderViewHost can deal with that message.
2072 RecordAction(UserMetricsAction("BadMessageTerminate_RWH5"));
2073 GetProcess()->ReceivedBadMessage();
2076 void RenderWidgetHostImpl::OnHasTouchEventHandlers(bool has_handlers
) {
2077 if (has_touch_handler_
== has_handlers
)
2079 has_touch_handler_
= has_handlers
;
2080 if (!has_touch_handler_
)
2081 touch_event_queue_
->FlushQueue();
2082 #if defined(OS_ANDROID)
2084 view_
->HasTouchEventHandlers(has_touch_handler_
);
2088 void RenderWidgetHostImpl::OnSetCursor(const WebCursor
& cursor
) {
2092 view_
->UpdateCursor(cursor
);
2095 void RenderWidgetHostImpl::OnTextInputTypeChanged(ui::TextInputType type
,
2096 bool can_compose_inline
) {
2098 view_
->TextInputTypeChanged(type
, can_compose_inline
);
2101 void RenderWidgetHostImpl::OnImeCompositionRangeChanged(
2102 const ui::Range
& range
,
2103 const std::vector
<gfx::Rect
>& character_bounds
) {
2105 view_
->ImeCompositionRangeChanged(range
, character_bounds
);
2108 void RenderWidgetHostImpl::OnImeCancelComposition() {
2110 view_
->ImeCancelComposition();
2113 void RenderWidgetHostImpl::OnDidActivateAcceleratedCompositing(bool activated
) {
2114 TRACE_EVENT1("renderer_host",
2115 "RenderWidgetHostImpl::OnDidActivateAcceleratedCompositing",
2116 "activated", activated
);
2117 is_accelerated_compositing_active_
= activated
;
2119 view_
->OnAcceleratedCompositingStateChange();
2122 void RenderWidgetHostImpl::OnLockMouse(bool user_gesture
,
2123 bool last_unlocked_by_target
,
2126 if (pending_mouse_lock_request_
) {
2127 Send(new ViewMsg_LockMouse_ACK(routing_id_
, false));
2129 } else if (IsMouseLocked()) {
2130 Send(new ViewMsg_LockMouse_ACK(routing_id_
, true));
2134 pending_mouse_lock_request_
= true;
2135 if (privileged
&& allow_privileged_mouse_lock_
) {
2136 // Directly approve to lock the mouse.
2137 GotResponseToLockMouseRequest(true);
2139 RequestToLockMouse(user_gesture
, last_unlocked_by_target
);
2143 void RenderWidgetHostImpl::OnUnlockMouse() {
2144 RejectMouseLockOrUnlockIfNecessary();
2147 void RenderWidgetHostImpl::OnShowDisambiguationPopup(
2148 const gfx::Rect
& rect
,
2149 const gfx::Size
& size
,
2150 const TransportDIB::Id
& id
) {
2151 DCHECK(!rect
.IsEmpty());
2152 DCHECK(!size
.IsEmpty());
2154 TransportDIB
* dib
= process_
->GetTransportDIB(id
);
2155 DCHECK(dib
->memory());
2156 DCHECK(dib
->size() == SkBitmap::ComputeSize(SkBitmap::kARGB_8888_Config
,
2157 size
.width(), size
.height()));
2159 SkBitmap zoomed_bitmap
;
2160 zoomed_bitmap
.setConfig(SkBitmap::kARGB_8888_Config
,
2161 size
.width(), size
.height());
2162 zoomed_bitmap
.setPixels(dib
->memory());
2164 #if defined(OS_ANDROID)
2166 view_
->ShowDisambiguationPopup(rect
, zoomed_bitmap
);
2171 zoomed_bitmap
.setPixels(0);
2172 Send(new ViewMsg_ReleaseDisambiguationPopupDIB(GetRoutingID(),
2177 void RenderWidgetHostImpl::OnWindowlessPluginDummyWindowCreated(
2178 gfx::NativeViewId dummy_activation_window
) {
2179 HWND hwnd
= reinterpret_cast<HWND
>(dummy_activation_window
);
2180 if (!IsWindow(hwnd
) ||
2181 !WebPluginDelegateImpl::IsDummyActivationWindow(hwnd
)) {
2182 // This may happen as a result of a race condition when the plugin is going
2187 SetParent(hwnd
, reinterpret_cast<HWND
>(GetNativeViewId()));
2188 dummy_windows_for_activation_
.push_back(hwnd
);
2191 void RenderWidgetHostImpl::OnWindowlessPluginDummyWindowDestroyed(
2192 gfx::NativeViewId dummy_activation_window
) {
2193 HWND hwnd
= reinterpret_cast<HWND
>(dummy_activation_window
);
2194 std::list
<HWND
>::iterator i
= dummy_windows_for_activation_
.begin();
2195 for (; i
!= dummy_windows_for_activation_
.end(); ++i
) {
2197 dummy_windows_for_activation_
.erase(i
);
2201 NOTREACHED() << "Unknown dummy window";
2205 bool RenderWidgetHostImpl::PaintBackingStoreRect(
2206 TransportDIB::Id bitmap
,
2207 const gfx::Rect
& bitmap_rect
,
2208 const std::vector
<gfx::Rect
>& copy_rects
,
2209 const gfx::Size
& view_size
,
2211 const base::Closure
& completion_callback
) {
2212 // The view may be destroyed already.
2217 // Don't bother updating the backing store when we're hidden. Just mark it
2218 // as being totally invalid. This will cause a complete repaint when the
2219 // view is restored.
2220 needs_repainting_on_restore_
= true;
2224 bool needs_full_paint
= false;
2225 bool scheduled_completion_callback
= false;
2226 BackingStoreManager::PrepareBackingStore(this, view_size
, bitmap
, bitmap_rect
,
2227 copy_rects
, scale_factor
,
2228 completion_callback
,
2230 &scheduled_completion_callback
);
2231 if (needs_full_paint
) {
2232 repaint_start_time_
= TimeTicks::Now();
2233 DCHECK(!repaint_ack_pending_
);
2234 repaint_ack_pending_
= true;
2235 TRACE_EVENT_ASYNC_BEGIN0(
2236 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
2237 Send(new ViewMsg_Repaint(routing_id_
, view_size
));
2240 return scheduled_completion_callback
;
2243 void RenderWidgetHostImpl::ScrollBackingStoreRect(const gfx::Vector2d
& delta
,
2244 const gfx::Rect
& clip_rect
,
2245 const gfx::Size
& view_size
) {
2247 // Don't bother updating the backing store when we're hidden. Just mark it
2248 // as being totally invalid. This will cause a complete repaint when the
2249 // view is restored.
2250 needs_repainting_on_restore_
= true;
2254 // TODO(darin): do we need to do something else if our backing store is not
2255 // the same size as the advertised view? maybe we just assume there is a
2256 // full paint on its way?
2257 BackingStore
* backing_store
= BackingStoreManager::Lookup(this);
2258 if (!backing_store
|| (backing_store
->size() != view_size
))
2260 backing_store
->ScrollBackingStore(delta
, clip_rect
, view_size
);
2263 void RenderWidgetHostImpl::Replace(const string16
& word
) {
2264 Send(new InputMsg_Replace(routing_id_
, word
));
2267 void RenderWidgetHostImpl::ReplaceMisspelling(const string16
& word
) {
2268 Send(new InputMsg_ReplaceMisspelling(routing_id_
, word
));
2271 void RenderWidgetHostImpl::SetIgnoreInputEvents(bool ignore_input_events
) {
2272 ignore_input_events_
= ignore_input_events
;
2275 bool RenderWidgetHostImpl::KeyPressListenersHandleEvent(
2276 const NativeWebKeyboardEvent
& event
) {
2277 if (event
.skip_in_browser
|| event
.type
!= WebKeyboardEvent::RawKeyDown
)
2280 ObserverList
<KeyboardListener
>::Iterator
it(keyboard_listeners_
);
2281 KeyboardListener
* listener
;
2282 while ((listener
= it
.GetNext()) != NULL
) {
2283 if (listener
->HandleKeyPressEvent(event
))
2290 void RenderWidgetHostImpl::ProcessKeyboardEventAck(int type
, bool processed
) {
2291 if (key_queue_
.empty()) {
2292 LOG(ERROR
) << "Got a KeyEvent back from the renderer but we "
2293 << "don't seem to have sent it to the renderer!";
2294 } else if (key_queue_
.front().type
!= type
) {
2295 LOG(ERROR
) << "We seem to have a different key type sent from "
2296 << "the renderer. (" << key_queue_
.front().type
<< " vs. "
2297 << type
<< "). Ignoring event.";
2299 // Something must be wrong. Clear the |key_queue_| and
2300 // |suppress_next_char_events_| so that we can resume from the error.
2302 suppress_next_char_events_
= false;
2304 NativeWebKeyboardEvent front_item
= key_queue_
.front();
2305 key_queue_
.pop_front();
2307 #if defined(OS_MACOSX)
2308 if (!is_hidden_
&& view_
->PostProcessEventForPluginIme(front_item
))
2312 // We only send unprocessed key event upwards if we are not hidden,
2313 // because the user has moved away from us and no longer expect any effect
2314 // of this key event.
2315 if (delegate_
&& !processed
&& !is_hidden_
&& !front_item
.skip_in_browser
) {
2316 delegate_
->HandleKeyboardEvent(front_item
);
2318 // WARNING: This RenderWidgetHostImpl can be deallocated at this point
2319 // (i.e. in the case of Ctrl+W, where the call to
2320 // HandleKeyboardEvent destroys this RenderWidgetHostImpl).
2325 const gfx::Vector2d
& RenderWidgetHostImpl::GetLastScrollOffset() const {
2326 return last_scroll_offset_
;
2329 bool RenderWidgetHostImpl::ShouldForwardTouchEvent() const {
2330 // Always send a touch event if the renderer has a touch-event handler. It is
2331 // possible that a renderer stops listening to touch-events while there are
2332 // still events in the touch-queue. In such cases, the new events should still
2333 // get into the queue.
2334 return has_touch_handler_
|| !touch_event_queue_
->empty();
2337 void RenderWidgetHostImpl::StartUserGesture() {
2341 void RenderWidgetHostImpl::Stop() {
2342 Send(new ViewMsg_Stop(GetRoutingID()));
2345 void RenderWidgetHostImpl::SetBackground(const SkBitmap
& background
) {
2346 Send(new ViewMsg_SetBackground(GetRoutingID(), background
));
2349 void RenderWidgetHostImpl::SetEditCommandsForNextKeyEvent(
2350 const std::vector
<EditCommand
>& commands
) {
2351 Send(new InputMsg_SetEditCommandsForNextKeyEvent(GetRoutingID(), commands
));
2354 void RenderWidgetHostImpl::SetAccessibilityMode(AccessibilityMode mode
) {
2355 accessibility_mode_
= mode
;
2356 Send(new ViewMsg_SetAccessibilityMode(routing_id_
, mode
));
2359 void RenderWidgetHostImpl::AccessibilityDoDefaultAction(int object_id
) {
2360 Send(new AccessibilityMsg_DoDefaultAction(GetRoutingID(), object_id
));
2363 void RenderWidgetHostImpl::AccessibilitySetFocus(int object_id
) {
2364 Send(new AccessibilityMsg_SetFocus(GetRoutingID(), object_id
));
2367 void RenderWidgetHostImpl::AccessibilityScrollToMakeVisible(
2368 int acc_obj_id
, gfx::Rect subfocus
) {
2369 Send(new AccessibilityMsg_ScrollToMakeVisible(
2370 GetRoutingID(), acc_obj_id
, subfocus
));
2373 void RenderWidgetHostImpl::AccessibilityScrollToPoint(
2374 int acc_obj_id
, gfx::Point point
) {
2375 Send(new AccessibilityMsg_ScrollToPoint(
2376 GetRoutingID(), acc_obj_id
, point
));
2379 void RenderWidgetHostImpl::AccessibilitySetTextSelection(
2380 int object_id
, int start_offset
, int end_offset
) {
2381 Send(new AccessibilityMsg_SetTextSelection(
2382 GetRoutingID(), object_id
, start_offset
, end_offset
));
2385 void RenderWidgetHostImpl::FatalAccessibilityTreeError() {
2386 Send(new AccessibilityMsg_FatalError(GetRoutingID()));
2389 #if defined(OS_WIN) && defined(USE_AURA)
2390 void RenderWidgetHostImpl::SetParentNativeViewAccessible(
2391 gfx::NativeViewAccessible accessible_parent
) {
2393 view_
->SetParentNativeViewAccessible(accessible_parent
);
2396 gfx::NativeViewAccessible
2397 RenderWidgetHostImpl::GetParentNativeViewAccessible() const {
2398 return delegate_
->GetParentNativeViewAccessible();
2402 void RenderWidgetHostImpl::ExecuteEditCommand(const std::string
& command
,
2403 const std::string
& value
) {
2404 Send(new InputMsg_ExecuteEditCommand(GetRoutingID(), command
, value
));
2407 void RenderWidgetHostImpl::ScrollFocusedEditableNodeIntoRect(
2408 const gfx::Rect
& rect
) {
2409 Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(GetRoutingID(), rect
));
2412 void RenderWidgetHostImpl::SelectRange(const gfx::Point
& start
,
2413 const gfx::Point
& end
) {
2414 if (select_range_pending_
) {
2415 if (!next_selection_range_
) {
2416 next_selection_range_
.reset(new SelectionRange());
2418 next_selection_range_
->start
= start
;
2419 next_selection_range_
->end
= end
;
2423 select_range_pending_
= true;
2424 Send(new InputMsg_SelectRange(GetRoutingID(), start
, end
));
2427 void RenderWidgetHostImpl::MoveCaret(const gfx::Point
& point
) {
2428 if (move_caret_pending_
) {
2429 next_move_caret_
.reset(new gfx::Point(point
));
2433 move_caret_pending_
= true;
2434 Send(new InputMsg_MoveCaret(GetRoutingID(), point
));
2437 void RenderWidgetHostImpl::Undo() {
2438 Send(new InputMsg_Undo(GetRoutingID()));
2439 RecordAction(UserMetricsAction("Undo"));
2442 void RenderWidgetHostImpl::Redo() {
2443 Send(new InputMsg_Redo(GetRoutingID()));
2444 RecordAction(UserMetricsAction("Redo"));
2447 void RenderWidgetHostImpl::Cut() {
2448 Send(new InputMsg_Cut(GetRoutingID()));
2449 RecordAction(UserMetricsAction("Cut"));
2452 void RenderWidgetHostImpl::Copy() {
2453 Send(new InputMsg_Copy(GetRoutingID()));
2454 RecordAction(UserMetricsAction("Copy"));
2457 void RenderWidgetHostImpl::CopyToFindPboard() {
2458 #if defined(OS_MACOSX)
2459 // Windows/Linux don't have the concept of a find pasteboard.
2460 Send(new InputMsg_CopyToFindPboard(GetRoutingID()));
2461 RecordAction(UserMetricsAction("CopyToFindPboard"));
2465 void RenderWidgetHostImpl::Paste() {
2466 Send(new InputMsg_Paste(GetRoutingID()));
2467 RecordAction(UserMetricsAction("Paste"));
2470 void RenderWidgetHostImpl::PasteAndMatchStyle() {
2471 Send(new InputMsg_PasteAndMatchStyle(GetRoutingID()));
2472 RecordAction(UserMetricsAction("PasteAndMatchStyle"));
2475 void RenderWidgetHostImpl::Delete() {
2476 Send(new InputMsg_Delete(GetRoutingID()));
2477 RecordAction(UserMetricsAction("DeleteSelection"));
2480 void RenderWidgetHostImpl::SelectAll() {
2481 Send(new InputMsg_SelectAll(GetRoutingID()));
2482 RecordAction(UserMetricsAction("SelectAll"));
2485 void RenderWidgetHostImpl::Unselect() {
2486 Send(new InputMsg_Unselect(GetRoutingID()));
2487 RecordAction(UserMetricsAction("Unselect"));
2490 bool RenderWidgetHostImpl::GotResponseToLockMouseRequest(bool allowed
) {
2492 RejectMouseLockOrUnlockIfNecessary();
2495 if (!pending_mouse_lock_request_
) {
2496 // This is possible, e.g., the plugin sends us an unlock request before
2497 // the user allows to lock to mouse.
2501 pending_mouse_lock_request_
= false;
2502 if (!view_
|| !view_
->HasFocus()|| !view_
->LockMouse()) {
2503 Send(new ViewMsg_LockMouse_ACK(routing_id_
, false));
2506 Send(new ViewMsg_LockMouse_ACK(routing_id_
, true));
2513 void RenderWidgetHostImpl::AcknowledgeBufferPresent(
2514 int32 route_id
, int gpu_host_id
,
2515 const AcceleratedSurfaceMsg_BufferPresented_Params
& params
) {
2516 GpuProcessHostUIShim
* ui_shim
= GpuProcessHostUIShim::FromID(gpu_host_id
);
2518 ui_shim
->Send(new AcceleratedSurfaceMsg_BufferPresented(route_id
,
2524 void RenderWidgetHostImpl::SendSwapCompositorFrameAck(
2525 int32 route_id
, int renderer_host_id
, const cc::CompositorFrameAck
& ack
) {
2526 RenderProcessHost
* host
= RenderProcessHost::FromID(renderer_host_id
);
2528 host
->Send(new ViewMsg_SwapCompositorFrameAck(route_id
, ack
));
2531 void RenderWidgetHostImpl::AcknowledgeSwapBuffersToRenderer() {
2532 if (!is_threaded_compositing_enabled_
)
2533 Send(new ViewMsg_SwapBuffers_ACK(routing_id_
));
2536 #if defined(USE_AURA)
2538 void RenderWidgetHostImpl::ParentChanged(gfx::NativeViewId new_parent
) {
2540 HWND hwnd
= reinterpret_cast<HWND
>(new_parent
);
2542 hwnd
= WebPluginDelegateImpl::GetDefaultWindowParent();
2543 for (std::list
<HWND
>::iterator i
= dummy_windows_for_activation_
.begin();
2544 i
!= dummy_windows_for_activation_
.end(); ++i
) {
2545 SetParent(*i
, hwnd
);
2552 void RenderWidgetHostImpl::DelayedAutoResized() {
2553 gfx::Size new_size
= new_auto_size_
;
2554 // Clear the new_auto_size_ since the empty value is used as a flag to
2555 // indicate that no callback is in progress (i.e. without this line
2556 // DelayedAutoResized will not get called again).
2557 new_auto_size_
.SetSize(0, 0);
2558 if (!should_auto_resize_
)
2561 OnRenderAutoResized(new_size
);
2564 void RenderWidgetHostImpl::DetachDelegate() {
2568 void RenderWidgetHostImpl::FrameSwapped(const ui::LatencyInfo
& latency_info
) {
2569 ui::LatencyInfo::LatencyMap::const_iterator l
=
2570 latency_info
.latency_components
.find(std::make_pair(
2571 ui::INPUT_EVENT_LATENCY_RWH_COMPONENT
, GetLatencyComponentId()));
2572 if (l
== latency_info
.latency_components
.end())
2575 rendering_stats_
.input_event_count
+= l
->second
.event_count
;
2576 rendering_stats_
.total_input_latency
+=
2577 l
->second
.event_count
*
2578 (latency_info
.swap_timestamp
- l
->second
.event_time
);
2580 if (CommandLine::ForCurrentProcess()->HasSwitch(
2581 switches::kEnableGpuBenchmarking
))
2582 Send(new ViewMsg_SetBrowserRenderingStats(routing_id_
, rendering_stats_
));
2586 void RenderWidgetHostImpl::CompositorFrameDrawn(
2587 const ui::LatencyInfo
& latency_info
) {
2588 for (ui::LatencyInfo::LatencyMap::const_iterator b
=
2589 latency_info
.latency_components
.begin();
2590 b
!= latency_info
.latency_components
.end();
2592 if (b
->first
.first
!= ui::INPUT_EVENT_LATENCY_RWH_COMPONENT
)
2594 // Matches with GetLatencyComponentId
2595 int routing_id
= b
->first
.second
& 0xffffffff;
2596 int process_id
= (b
->first
.second
>> 32) & 0xffffffff;
2597 RenderWidgetHost
* rwh
=
2598 RenderWidgetHost::FromID(process_id
, routing_id
);
2601 RenderWidgetHostImpl::From(rwh
)->FrameSwapped(latency_info
);
2605 } // namespace content