OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/renderer_host/input/input_router_impl.h" | 5 #include "content/browser/renderer_host/input/input_router_impl.h" |
6 | 6 |
7 #include <math.h> | 7 #include <math.h> |
8 | 8 |
9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
11 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
12 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
13 #include "content/browser/renderer_host/input/gesture_event_queue.h" | |
14 #include "content/browser/renderer_host/input/input_ack_handler.h" | 13 #include "content/browser/renderer_host/input/input_ack_handler.h" |
15 #include "content/browser/renderer_host/input/input_router_client.h" | 14 #include "content/browser/renderer_host/input/input_router_client.h" |
16 #include "content/browser/renderer_host/input/touch_event_queue.h" | |
17 #include "content/browser/renderer_host/input/touchpad_tap_suppression_controlle
r.h" | 15 #include "content/browser/renderer_host/input/touchpad_tap_suppression_controlle
r.h" |
18 #include "content/common/content_constants_internal.h" | 16 #include "content/common/content_constants_internal.h" |
19 #include "content/common/edit_command.h" | 17 #include "content/common/edit_command.h" |
20 #include "content/common/input/input_event_ack_state.h" | 18 #include "content/common/input/input_event_ack_state.h" |
21 #include "content/common/input/touch_action.h" | 19 #include "content/common/input/touch_action.h" |
22 #include "content/common/input/web_touch_event_traits.h" | 20 #include "content/common/input/web_touch_event_traits.h" |
23 #include "content/common/input_messages.h" | 21 #include "content/common/input_messages.h" |
24 #include "content/common/view_messages.h" | 22 #include "content/common/view_messages.h" |
25 #include "content/public/browser/notification_service.h" | 23 #include "content/public/browser/notification_service.h" |
26 #include "content/public/browser/notification_types.h" | 24 #include "content/public/browser/notification_types.h" |
(...skipping 23 matching lines...) Expand all Loading... |
50 case INPUT_EVENT_ACK_STATE_NOT_CONSUMED: return "NOT_CONSUMED"; | 48 case INPUT_EVENT_ACK_STATE_NOT_CONSUMED: return "NOT_CONSUMED"; |
51 case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS: return "NO_CONSUMER_EXISTS"; | 49 case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS: return "NO_CONSUMER_EXISTS"; |
52 case INPUT_EVENT_ACK_STATE_IGNORED: return "IGNORED"; | 50 case INPUT_EVENT_ACK_STATE_IGNORED: return "IGNORED"; |
53 } | 51 } |
54 DLOG(WARNING) << "Unhandled InputEventAckState in GetEventAckName."; | 52 DLOG(WARNING) << "Unhandled InputEventAckState in GetEventAckName."; |
55 return ""; | 53 return ""; |
56 } | 54 } |
57 | 55 |
58 } // namespace | 56 } // namespace |
59 | 57 |
60 InputRouterImpl::Config::Config() {} | 58 InputRouterImpl::Config::Config() : buffer_wheel_events_until_flush(false) {} |
61 | 59 |
62 InputRouterImpl::InputRouterImpl(IPC::Sender* sender, | 60 InputRouterImpl::InputRouterImpl(IPC::Sender* sender, |
63 InputRouterClient* client, | 61 InputRouterClient* client, |
64 InputAckHandler* ack_handler, | 62 InputAckHandler* ack_handler, |
65 int routing_id, | 63 int routing_id, |
66 const Config& config) | 64 const Config& config) |
67 : sender_(sender), | 65 : sender_(sender), |
68 client_(client), | 66 client_(client), |
69 ack_handler_(ack_handler), | 67 ack_handler_(ack_handler), |
70 routing_id_(routing_id), | 68 routing_id_(routing_id), |
71 select_message_pending_(false), | 69 select_message_pending_(false), |
72 move_caret_pending_(false), | 70 move_caret_pending_(false), |
73 mouse_move_pending_(false), | 71 mouse_move_pending_(false), |
74 mouse_wheel_pending_(false), | |
75 current_ack_source_(ACK_SOURCE_NONE), | 72 current_ack_source_(ACK_SOURCE_NONE), |
76 flush_requested_(false), | 73 flush_requested_(false), |
77 active_renderer_fling_count_(0), | 74 active_renderer_fling_count_(0), |
78 touch_event_queue_(this, config.touch_config), | 75 touch_event_queue_(this, config.touch_config), |
79 gesture_event_queue_(this, this, config.gesture_config) { | 76 gesture_event_queue_(this, this, config.gesture_config), |
| 77 wheel_event_queue_(this, config.buffer_wheel_events_until_flush) { |
80 DCHECK(sender); | 78 DCHECK(sender); |
81 DCHECK(client); | 79 DCHECK(client); |
82 DCHECK(ack_handler); | 80 DCHECK(ack_handler); |
83 UpdateTouchAckTimeoutEnabled(); | 81 UpdateTouchAckTimeoutEnabled(); |
84 } | 82 } |
85 | 83 |
86 InputRouterImpl::~InputRouterImpl() { | 84 InputRouterImpl::~InputRouterImpl() { |
87 STLDeleteElements(&pending_select_messages_); | 85 STLDeleteElements(&pending_select_messages_); |
88 } | 86 } |
89 | 87 |
90 bool InputRouterImpl::SendInput(scoped_ptr<IPC::Message> message) { | 88 bool InputRouterImpl::SendInput(scoped_ptr<IPC::Message> message) { |
91 DCHECK(IPC_MESSAGE_ID_CLASS(message->type()) == InputMsgStart); | 89 DCHECK(IPC_MESSAGE_ID_CLASS(message->type()) == InputMsgStart); |
92 switch (message->type()) { | 90 switch (message->type()) { |
93 // Check for types that require an ACK. | 91 // Check for types that require an ACK. |
94 case InputMsg_SelectRange::ID: | 92 case InputMsg_SelectRange::ID: |
95 case InputMsg_MoveRangeSelectionExtent::ID: | 93 case InputMsg_MoveRangeSelectionExtent::ID: |
96 return SendSelectMessage(message.Pass()); | 94 return SendSelectMessage(message.Pass()); |
97 case InputMsg_MoveCaret::ID: | 95 case InputMsg_MoveCaret::ID: |
98 return SendMoveCaret(message.Pass()); | 96 return SendMoveCaret(message.Pass()); |
99 case InputMsg_HandleInputEvent::ID: | 97 case InputMsg_HandleInputEvent::ID: |
100 NOTREACHED() << "WebInputEvents should never be sent via SendInput."; | 98 NOTREACHED() << "WebInputEvents should never be sent via SendInput."; |
101 return false; | 99 return false; |
102 default: | 100 default: |
103 return Send(message.release()); | 101 return Send(message.release()); |
104 } | 102 } |
105 } | 103 } |
106 | 104 |
107 void InputRouterImpl::FlushInput(base::TimeTicks flush_time) { | 105 void InputRouterImpl::FlushInput(base::TimeTicks flush_time) { |
108 flush_requested_ = true; | 106 flush_requested_ = true; |
| 107 |
| 108 wheel_event_queue_.Flush(); |
| 109 |
109 SignalFlushedIfNecessary(); | 110 SignalFlushedIfNecessary(); |
110 } | 111 } |
111 | 112 |
112 void InputRouterImpl::SendMouseEvent( | 113 void InputRouterImpl::SendMouseEvent( |
113 const MouseEventWithLatencyInfo& mouse_event) { | 114 const MouseEventWithLatencyInfo& mouse_event) { |
114 if (mouse_event.event.type == WebInputEvent::MouseDown && | 115 if (mouse_event.event.type == WebInputEvent::MouseDown && |
115 gesture_event_queue_.GetTouchpadTapSuppressionController()-> | 116 gesture_event_queue_.GetTouchpadTapSuppressionController()-> |
116 ShouldDeferMouseDown(mouse_event)) | 117 ShouldDeferMouseDown(mouse_event)) |
117 return; | 118 return; |
118 if (mouse_event.event.type == WebInputEvent::MouseUp && | 119 if (mouse_event.event.type == WebInputEvent::MouseUp && |
119 gesture_event_queue_.GetTouchpadTapSuppressionController()-> | 120 gesture_event_queue_.GetTouchpadTapSuppressionController()-> |
120 ShouldSuppressMouseUp()) | 121 ShouldSuppressMouseUp()) |
121 return; | 122 return; |
122 | 123 |
123 SendMouseEventImmediately(mouse_event); | 124 SendMouseEventImmediately(mouse_event); |
124 } | 125 } |
125 | 126 |
126 void InputRouterImpl::SendWheelEvent( | 127 void InputRouterImpl::SendWheelEvent( |
127 const MouseWheelEventWithLatencyInfo& wheel_event) { | 128 const MouseWheelEventWithLatencyInfo& wheel_event) { |
128 if (mouse_wheel_pending_) { | 129 wheel_event_queue_.QueueEvent(wheel_event); |
129 // If there's already a mouse wheel event waiting to be sent to the | |
130 // renderer, add the new deltas to that event. Not doing so (e.g., by | |
131 // dropping the old event, as for mouse moves) results in very slow | |
132 // scrolling on the Mac. | |
133 if (wheel_event.event.hasPreciseScrollingDeltas) | |
134 DCHECK(wheel_event.event.canScroll); | |
135 DCHECK(!(wheel_event.event.hasPreciseScrollingDeltas && | |
136 !wheel_event.event.canScroll)); | |
137 if (coalesced_mouse_wheel_events_.empty() || | |
138 (!coalesced_mouse_wheel_events_.empty() && | |
139 !coalesced_mouse_wheel_events_.back().CanCoalesceWith(wheel_event))) { | |
140 coalesced_mouse_wheel_events_.push_back(wheel_event); | |
141 } else { | |
142 coalesced_mouse_wheel_events_.back().CoalesceWith(wheel_event); | |
143 TRACE_EVENT_INSTANT2("input", "InputRouterImpl::CoalescedWheelEvent", | |
144 TRACE_EVENT_SCOPE_THREAD, | |
145 "total_dx", | |
146 coalesced_mouse_wheel_events_.back().event.deltaX, | |
147 "total_dy", | |
148 coalesced_mouse_wheel_events_.back().event.deltaY); | |
149 } | |
150 return; | |
151 } | |
152 | |
153 mouse_wheel_pending_ = true; | |
154 current_wheel_event_ = wheel_event; | |
155 | |
156 LOCAL_HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize", | |
157 coalesced_mouse_wheel_events_.size()); | |
158 | |
159 FilterAndSendWebInputEvent(wheel_event.event, wheel_event.latency); | |
160 } | 130 } |
161 | 131 |
162 void InputRouterImpl::SendKeyboardEvent( | 132 void InputRouterImpl::SendKeyboardEvent( |
163 const NativeWebKeyboardEventWithLatencyInfo& key_event) { | 133 const NativeWebKeyboardEventWithLatencyInfo& key_event) { |
164 // Put all WebKeyboardEvent objects in a queue since we can't trust the | 134 // Put all WebKeyboardEvent objects in a queue since we can't trust the |
165 // renderer and we need to give something to the HandleKeyboardEvent | 135 // renderer and we need to give something to the HandleKeyboardEvent |
166 // handler. | 136 // handler. |
167 key_queue_.push_back(key_event); | 137 key_queue_.push_back(key_event); |
168 LOCAL_HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size()); | 138 LOCAL_HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size()); |
169 | 139 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 } | 213 } |
244 | 214 |
245 void InputRouterImpl::NotifySiteIsMobileOptimized(bool is_mobile_optimized) { | 215 void InputRouterImpl::NotifySiteIsMobileOptimized(bool is_mobile_optimized) { |
246 touch_event_queue_.SetIsMobileOptimizedSite(is_mobile_optimized); | 216 touch_event_queue_.SetIsMobileOptimizedSite(is_mobile_optimized); |
247 } | 217 } |
248 | 218 |
249 bool InputRouterImpl::HasPendingEvents() const { | 219 bool InputRouterImpl::HasPendingEvents() const { |
250 return !touch_event_queue_.empty() || | 220 return !touch_event_queue_.empty() || |
251 !gesture_event_queue_.empty() || | 221 !gesture_event_queue_.empty() || |
252 !key_queue_.empty() || | 222 !key_queue_.empty() || |
| 223 !wheel_event_queue_.empty() || |
253 mouse_move_pending_ || | 224 mouse_move_pending_ || |
254 mouse_wheel_pending_ || | |
255 select_message_pending_ || | 225 select_message_pending_ || |
256 move_caret_pending_ || | 226 move_caret_pending_ || |
257 active_renderer_fling_count_ > 0; | 227 active_renderer_fling_count_ > 0; |
258 } | 228 } |
259 | 229 |
260 bool InputRouterImpl::OnMessageReceived(const IPC::Message& message) { | 230 bool InputRouterImpl::OnMessageReceived(const IPC::Message& message) { |
261 bool handled = true; | 231 bool handled = true; |
262 IPC_BEGIN_MESSAGE_MAP(InputRouterImpl, message) | 232 IPC_BEGIN_MESSAGE_MAP(InputRouterImpl, message) |
263 IPC_MESSAGE_HANDLER(InputHostMsg_HandleInputEvent_ACK, OnInputEventAck) | 233 IPC_MESSAGE_HANDLER(InputHostMsg_HandleInputEvent_ACK, OnInputEventAck) |
264 IPC_MESSAGE_HANDLER(InputHostMsg_DidOverscroll, OnDidOverscroll) | 234 IPC_MESSAGE_HANDLER(InputHostMsg_DidOverscroll, OnDidOverscroll) |
(...skipping 24 matching lines...) Expand all Loading... |
289 ack_handler_->OnTouchEventAck(event, ack_result); | 259 ack_handler_->OnTouchEventAck(event, ack_result); |
290 } | 260 } |
291 | 261 |
292 void InputRouterImpl::OnGestureEventAck( | 262 void InputRouterImpl::OnGestureEventAck( |
293 const GestureEventWithLatencyInfo& event, | 263 const GestureEventWithLatencyInfo& event, |
294 InputEventAckState ack_result) { | 264 InputEventAckState ack_result) { |
295 touch_event_queue_.OnGestureEventAck(event, ack_result); | 265 touch_event_queue_.OnGestureEventAck(event, ack_result); |
296 ack_handler_->OnGestureEventAck(event, ack_result); | 266 ack_handler_->OnGestureEventAck(event, ack_result); |
297 } | 267 } |
298 | 268 |
| 269 void InputRouterImpl::SendWheelEventImmediately( |
| 270 const MouseWheelEventWithLatencyInfo& wheel_event) { |
| 271 FilterAndSendWebInputEvent(wheel_event.event, wheel_event.latency); |
| 272 } |
| 273 |
| 274 void InputRouterImpl::OnWheelEventAck( |
| 275 const MouseWheelEventWithLatencyInfo& event, |
| 276 InputEventAckState ack_result) { |
| 277 ack_handler_->OnWheelEventAck(event, ack_result); |
| 278 } |
| 279 |
| 280 void InputRouterImpl::SetNeedsFlush() { |
| 281 client_->SetNeedsFlushInput(); |
| 282 } |
| 283 |
299 bool InputRouterImpl::SendSelectMessage( | 284 bool InputRouterImpl::SendSelectMessage( |
300 scoped_ptr<IPC::Message> message) { | 285 scoped_ptr<IPC::Message> message) { |
301 DCHECK(message->type() == InputMsg_SelectRange::ID || | 286 DCHECK(message->type() == InputMsg_SelectRange::ID || |
302 message->type() == InputMsg_MoveRangeSelectionExtent::ID); | 287 message->type() == InputMsg_MoveRangeSelectionExtent::ID); |
303 | 288 |
304 // TODO(jdduke): Factor out common logic between selection and caret-related | 289 // TODO(jdduke): Factor out common logic between selection and caret-related |
305 // IPC messages. | 290 // IPC messages. |
306 if (select_message_pending_) { | 291 if (select_message_pending_) { |
307 if (!pending_select_messages_.empty() && | 292 if (!pending_select_messages_.empty() && |
308 pending_select_messages_.back()->type() == message->type()) { | 293 pending_select_messages_.back()->type() == message->type()) { |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 if (next_mouse_move_) { | 559 if (next_mouse_move_) { |
575 DCHECK(next_mouse_move_->event.type == WebInputEvent::MouseMove); | 560 DCHECK(next_mouse_move_->event.type == WebInputEvent::MouseMove); |
576 scoped_ptr<MouseEventWithLatencyInfo> next_mouse_move | 561 scoped_ptr<MouseEventWithLatencyInfo> next_mouse_move |
577 = next_mouse_move_.Pass(); | 562 = next_mouse_move_.Pass(); |
578 SendMouseEvent(*next_mouse_move); | 563 SendMouseEvent(*next_mouse_move); |
579 } | 564 } |
580 } | 565 } |
581 | 566 |
582 void InputRouterImpl::ProcessWheelAck(InputEventAckState ack_result, | 567 void InputRouterImpl::ProcessWheelAck(InputEventAckState ack_result, |
583 const ui::LatencyInfo& latency) { | 568 const ui::LatencyInfo& latency) { |
584 // TODO(miletus): Add renderer side latency to each uncoalesced mouse | 569 wheel_event_queue_.ProcessWheelAck(ack_result, latency); |
585 // wheel event and add terminal component to each of them. | |
586 current_wheel_event_.latency.AddNewLatencyFrom(latency); | |
587 | |
588 // Process the unhandled wheel event here before calling SendWheelEvent() | |
589 // since it will mutate current_wheel_event_. | |
590 ack_handler_->OnWheelEventAck(current_wheel_event_, ack_result); | |
591 | |
592 // Mark the wheel event complete only after the ACKs have been handled above. | |
593 // For example, ACKing the GesturePinchUpdate could cause another | |
594 // GesturePinchUpdate to be sent, which should queue a wheel event rather than | |
595 // send it immediately. | |
596 mouse_wheel_pending_ = false; | |
597 | |
598 // Send the next (coalesced or synthetic) mouse wheel event. | |
599 if (!coalesced_mouse_wheel_events_.empty()) { | |
600 MouseWheelEventWithLatencyInfo next_wheel_event = | |
601 coalesced_mouse_wheel_events_.front(); | |
602 coalesced_mouse_wheel_events_.pop_front(); | |
603 SendWheelEvent(next_wheel_event); | |
604 } | |
605 } | 570 } |
606 | 571 |
607 void InputRouterImpl::ProcessGestureAck(WebInputEvent::Type type, | 572 void InputRouterImpl::ProcessGestureAck(WebInputEvent::Type type, |
608 InputEventAckState ack_result, | 573 InputEventAckState ack_result, |
609 const ui::LatencyInfo& latency) { | 574 const ui::LatencyInfo& latency) { |
610 if (type == blink::WebInputEvent::GestureFlingStart && | 575 if (type == blink::WebInputEvent::GestureFlingStart && |
611 ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) { | 576 ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) { |
612 ++active_renderer_fling_count_; | 577 ++active_renderer_fling_count_; |
613 } | 578 } |
614 | 579 |
(...skipping 23 matching lines...) Expand all Loading... |
638 return; | 603 return; |
639 | 604 |
640 if (HasPendingEvents()) | 605 if (HasPendingEvents()) |
641 return; | 606 return; |
642 | 607 |
643 flush_requested_ = false; | 608 flush_requested_ = false; |
644 client_->DidFlushAllInput(); | 609 client_->DidFlushAllInput(); |
645 } | 610 } |
646 | 611 |
647 } // namespace content | 612 } // namespace content |
OLD | NEW |