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 "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 InputAckHandler* ack_handler, | 135 InputAckHandler* ack_handler, |
136 int routing_id) | 136 int routing_id) |
137 : sender_(sender), | 137 : sender_(sender), |
138 client_(client), | 138 client_(client), |
139 ack_handler_(ack_handler), | 139 ack_handler_(ack_handler), |
140 routing_id_(routing_id), | 140 routing_id_(routing_id), |
141 select_range_pending_(false), | 141 select_range_pending_(false), |
142 move_caret_pending_(false), | 142 move_caret_pending_(false), |
143 mouse_move_pending_(false), | 143 mouse_move_pending_(false), |
144 mouse_wheel_pending_(false), | 144 mouse_wheel_pending_(false), |
145 touch_ack_timeout_enabled_(false), | 145 touch_ack_timeout_supported_(false), |
146 touch_ack_timeout_delay_ms_(std::numeric_limits<size_t>::max()), | 146 touch_ack_timeout_delay_ms_(std::numeric_limits<size_t>::max()), |
| 147 current_view_flags_(0), |
147 current_ack_source_(ACK_SOURCE_NONE), | 148 current_ack_source_(ACK_SOURCE_NONE), |
148 gesture_event_queue_(new GestureEventQueue(this, this)) { | 149 gesture_event_queue_(new GestureEventQueue(this, this)) { |
149 DCHECK(sender); | 150 DCHECK(sender); |
150 DCHECK(client); | 151 DCHECK(client); |
151 DCHECK(ack_handler); | 152 DCHECK(ack_handler); |
152 touch_event_queue_.reset(new TouchEventQueue( | 153 touch_event_queue_.reset(new TouchEventQueue( |
153 this, GetTouchScrollingMode(), GetTouchMoveSlopSuppressionLengthDips())); | 154 this, GetTouchScrollingMode(), GetTouchMoveSlopSuppressionLengthDips())); |
154 touch_ack_timeout_enabled_ = | 155 touch_ack_timeout_supported_ = |
155 GetTouchAckTimeoutDelayMs(&touch_ack_timeout_delay_ms_); | 156 GetTouchAckTimeoutDelayMs(&touch_ack_timeout_delay_ms_); |
156 touch_event_queue_->SetAckTimeoutEnabled(touch_ack_timeout_enabled_, | 157 UpdateTouchAckTimeoutEnabled(); |
157 touch_ack_timeout_delay_ms_); | |
158 } | 158 } |
159 | 159 |
160 InputRouterImpl::~InputRouterImpl() {} | 160 InputRouterImpl::~InputRouterImpl() {} |
161 | 161 |
162 void InputRouterImpl::Flush() {} | 162 void InputRouterImpl::Flush() {} |
163 | 163 |
164 bool InputRouterImpl::SendInput(scoped_ptr<IPC::Message> message) { | 164 bool InputRouterImpl::SendInput(scoped_ptr<IPC::Message> message) { |
165 DCHECK(IPC_MESSAGE_ID_CLASS(message->type()) == InputMsgStart); | 165 DCHECK(IPC_MESSAGE_ID_CLASS(message->type()) == InputMsgStart); |
166 switch (message->type()) { | 166 switch (message->type()) { |
167 // Check for types that require an ACK. | 167 // Check for types that require an ACK. |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 return; | 280 return; |
281 } | 281 } |
282 mouse_move_pending_ = true; | 282 mouse_move_pending_ = true; |
283 } | 283 } |
284 | 284 |
285 FilterAndSendWebInputEvent(mouse_event.event, mouse_event.latency, false); | 285 FilterAndSendWebInputEvent(mouse_event.event, mouse_event.latency, false); |
286 } | 286 } |
287 | 287 |
288 void InputRouterImpl::SendTouchEventImmediately( | 288 void InputRouterImpl::SendTouchEventImmediately( |
289 const TouchEventWithLatencyInfo& touch_event) { | 289 const TouchEventWithLatencyInfo& touch_event) { |
290 if (WebTouchEventTraits::IsTouchSequenceStart(touch_event.event)) | 290 if (WebTouchEventTraits::IsTouchSequenceStart(touch_event.event)) { |
291 touch_action_filter_.ResetTouchAction(); | 291 touch_action_filter_.ResetTouchAction(); |
| 292 // Note that if the previous touch-action was TOUCH_ACTION_NONE, enabling |
| 293 // the timeout here will not take effect until the *following* touch |
| 294 // sequence. This is a desirable side-effect, giving the renderer a chance |
| 295 // to send a touch-action response without racing against the ack timeout. |
| 296 UpdateTouchAckTimeoutEnabled(); |
| 297 } |
292 | 298 |
293 FilterAndSendWebInputEvent(touch_event.event, touch_event.latency, false); | 299 FilterAndSendWebInputEvent(touch_event.event, touch_event.latency, false); |
294 } | 300 } |
295 | 301 |
296 void InputRouterImpl::SendGestureEventImmediately( | 302 void InputRouterImpl::SendGestureEventImmediately( |
297 const GestureEventWithLatencyInfo& gesture_event) { | 303 const GestureEventWithLatencyInfo& gesture_event) { |
298 FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false); | 304 FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false); |
299 } | 305 } |
300 | 306 |
301 const NativeWebKeyboardEvent* InputRouterImpl::GetLastKeyboardEvent() const { | 307 const NativeWebKeyboardEvent* InputRouterImpl::GetLastKeyboardEvent() const { |
302 if (key_queue_.empty()) | 308 if (key_queue_.empty()) |
303 return NULL; | 309 return NULL; |
304 return &key_queue_.front(); | 310 return &key_queue_.front(); |
305 } | 311 } |
306 | 312 |
307 bool InputRouterImpl::ShouldForwardTouchEvent() const { | 313 bool InputRouterImpl::ShouldForwardTouchEvent() const { |
308 // Always send a touch event if the renderer has a touch-event handler. | 314 // Always send a touch event if the renderer has a touch-event handler. |
309 return touch_event_queue_->has_handlers(); | 315 return touch_event_queue_->has_handlers(); |
310 } | 316 } |
311 | 317 |
312 void InputRouterImpl::OnViewUpdated(int view_flags) { | 318 void InputRouterImpl::OnViewUpdated(int view_flags) { |
313 bool fixed_page_scale = (view_flags & FIXED_PAGE_SCALE) != 0; | 319 current_view_flags_ = view_flags; |
314 bool mobile_viewport = (view_flags & MOBILE_VIEWPORT) != 0; | 320 |
315 touch_event_queue_->SetAckTimeoutEnabled( | 321 // A fixed page scale or mobile viewport should disable the touch ack timeout. |
316 touch_ack_timeout_enabled_ && !(fixed_page_scale || mobile_viewport), | 322 UpdateTouchAckTimeoutEnabled(); |
317 touch_ack_timeout_delay_ms_); | |
318 } | 323 } |
319 | 324 |
320 bool InputRouterImpl::OnMessageReceived(const IPC::Message& message) { | 325 bool InputRouterImpl::OnMessageReceived(const IPC::Message& message) { |
321 bool handled = true; | 326 bool handled = true; |
322 bool message_is_ok = true; | 327 bool message_is_ok = true; |
323 IPC_BEGIN_MESSAGE_MAP_EX(InputRouterImpl, message, message_is_ok) | 328 IPC_BEGIN_MESSAGE_MAP_EX(InputRouterImpl, message, message_is_ok) |
324 IPC_MESSAGE_HANDLER(InputHostMsg_HandleInputEvent_ACK, OnInputEventAck) | 329 IPC_MESSAGE_HANDLER(InputHostMsg_HandleInputEvent_ACK, OnInputEventAck) |
325 IPC_MESSAGE_HANDLER(ViewHostMsg_MoveCaret_ACK, OnMsgMoveCaretAck) | 330 IPC_MESSAGE_HANDLER(ViewHostMsg_MoveCaret_ACK, OnMsgMoveCaretAck) |
326 IPC_MESSAGE_HANDLER(ViewHostMsg_SelectRange_ACK, OnSelectRangeAck) | 331 IPC_MESSAGE_HANDLER(ViewHostMsg_SelectRange_ACK, OnSelectRangeAck) |
327 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers, | 332 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers, |
328 OnHasTouchEventHandlers) | 333 OnHasTouchEventHandlers) |
329 IPC_MESSAGE_HANDLER(InputHostMsg_SetTouchAction, | 334 IPC_MESSAGE_HANDLER(InputHostMsg_SetTouchAction, |
330 OnSetTouchAction) | 335 OnSetTouchAction) |
331 IPC_MESSAGE_UNHANDLED(handled = false) | 336 IPC_MESSAGE_UNHANDLED(handled = false) |
332 IPC_END_MESSAGE_MAP() | 337 IPC_END_MESSAGE_MAP() |
333 | 338 |
334 if (!message_is_ok) | 339 if (!message_is_ok) |
335 ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE); | 340 ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE); |
336 | 341 |
337 return handled; | 342 return handled; |
338 } | 343 } |
339 | 344 |
340 void InputRouterImpl::OnTouchEventAck(const TouchEventWithLatencyInfo& event, | 345 void InputRouterImpl::OnTouchEventAck(const TouchEventWithLatencyInfo& event, |
341 InputEventAckState ack_result) { | 346 InputEventAckState ack_result) { |
342 // Touchstart events sent to the renderer indicate a new touch sequence, but | 347 // Touchstart events sent to the renderer indicate a new touch sequence, but |
343 // in some cases we may filter out sending the touchstart - catch those here. | 348 // in some cases we may filter out sending the touchstart - catch those here. |
344 if (WebTouchEventTraits::IsTouchSequenceStart(event.event) && | 349 if (WebTouchEventTraits::IsTouchSequenceStart(event.event) && |
345 ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) { | 350 ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) { |
346 touch_action_filter_.ResetTouchAction(); | 351 touch_action_filter_.ResetTouchAction(); |
| 352 UpdateTouchAckTimeoutEnabled(); |
347 } | 353 } |
348 ack_handler_->OnTouchEventAck(event, ack_result); | 354 ack_handler_->OnTouchEventAck(event, ack_result); |
349 } | 355 } |
350 | 356 |
351 void InputRouterImpl::OnGestureEventAck( | 357 void InputRouterImpl::OnGestureEventAck( |
352 const GestureEventWithLatencyInfo& event, | 358 const GestureEventWithLatencyInfo& event, |
353 InputEventAckState ack_result) { | 359 InputEventAckState ack_result) { |
354 touch_event_queue_->OnGestureEventAck(event, ack_result); | 360 touch_event_queue_->OnGestureEventAck(event, ack_result); |
355 ProcessAckForOverscroll(event.event, ack_result); | 361 ProcessAckForOverscroll(event.event, ack_result); |
356 ack_handler_->OnGestureEventAck(event, ack_result); | 362 ack_handler_->OnGestureEventAck(event, ack_result); |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
552 } | 558 } |
553 | 559 |
554 void InputRouterImpl::OnHasTouchEventHandlers(bool has_handlers) { | 560 void InputRouterImpl::OnHasTouchEventHandlers(bool has_handlers) { |
555 TRACE_EVENT1("input", "InputRouterImpl::OnHasTouchEventHandlers", | 561 TRACE_EVENT1("input", "InputRouterImpl::OnHasTouchEventHandlers", |
556 "has_handlers", has_handlers); | 562 "has_handlers", has_handlers); |
557 | 563 |
558 touch_event_queue_->OnHasTouchEventHandlers(has_handlers); | 564 touch_event_queue_->OnHasTouchEventHandlers(has_handlers); |
559 client_->OnHasTouchEventHandlers(has_handlers); | 565 client_->OnHasTouchEventHandlers(has_handlers); |
560 } | 566 } |
561 | 567 |
562 void InputRouterImpl::OnSetTouchAction( | 568 void InputRouterImpl::OnSetTouchAction(TouchAction touch_action) { |
563 content::TouchAction touch_action) { | |
564 // Synthetic touchstart events should get filtered out in RenderWidget. | 569 // Synthetic touchstart events should get filtered out in RenderWidget. |
565 DCHECK(touch_event_queue_->IsPendingAckTouchStart()); | 570 DCHECK(touch_event_queue_->IsPendingAckTouchStart()); |
566 | 571 |
567 touch_action_filter_.OnSetTouchAction(touch_action); | 572 touch_action_filter_.OnSetTouchAction(touch_action); |
| 573 |
| 574 // TOUCH_ACTION_NONE should disable the touch ack timeout. |
| 575 UpdateTouchAckTimeoutEnabled(); |
568 } | 576 } |
569 | 577 |
570 void InputRouterImpl::ProcessInputEventAck( | 578 void InputRouterImpl::ProcessInputEventAck( |
571 WebInputEvent::Type event_type, | 579 WebInputEvent::Type event_type, |
572 InputEventAckState ack_result, | 580 InputEventAckState ack_result, |
573 const ui::LatencyInfo& latency_info, | 581 const ui::LatencyInfo& latency_info, |
574 AckSource ack_source) { | 582 AckSource ack_source) { |
575 TRACE_EVENT2("input", "InputRouterImpl::ProcessInputEventAck", | 583 TRACE_EVENT2("input", "InputRouterImpl::ProcessInputEventAck", |
576 "type", WebInputEventTraits::GetName(event_type), | 584 "type", WebInputEventTraits::GetName(event_type), |
577 "ack", GetEventAckName(ack_result)); | 585 "ack", GetEventAckName(ack_result)); |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
767 SendGestureEvent(MakeGestureEvent( | 775 SendGestureEvent(MakeGestureEvent( |
768 WebInputEvent::GestureScrollEnd, mouse_event.timeStampSeconds, | 776 WebInputEvent::GestureScrollEnd, mouse_event.timeStampSeconds, |
769 x, y, 0, event.latency)); | 777 x, y, 0, event.latency)); |
770 } | 778 } |
771 break; | 779 break; |
772 case WebMouseEvent::ButtonNone: | 780 case WebMouseEvent::ButtonNone: |
773 break; | 781 break; |
774 } | 782 } |
775 } | 783 } |
776 | 784 |
| 785 void InputRouterImpl::UpdateTouchAckTimeoutEnabled() { |
| 786 if (!touch_ack_timeout_supported_) { |
| 787 touch_event_queue_->SetAckTimeoutEnabled(false, 0); |
| 788 return; |
| 789 } |
| 790 |
| 791 // Mobile sites tend to be well-behaved with respect to touch handling, so |
| 792 // they have less need for the touch timeout fallback. |
| 793 const bool fixed_page_scale = (current_view_flags_ & FIXED_PAGE_SCALE) != 0; |
| 794 const bool mobile_viewport = (current_view_flags_ & MOBILE_VIEWPORT) != 0; |
| 795 |
| 796 // TOUCH_ACTION_NONE will prevent scrolling, in which case the timeout serves |
| 797 // little purpose. It's also a strong signal that touch handling is critical |
| 798 // to page functionality, so the timeout could do more harm than good. |
| 799 const bool touch_action_none = |
| 800 touch_action_filter_.allowed_touch_action() == TOUCH_ACTION_NONE; |
| 801 |
| 802 const bool touch_ack_timeout_enabled = !fixed_page_scale && |
| 803 !mobile_viewport && |
| 804 !touch_action_none; |
| 805 touch_event_queue_->SetAckTimeoutEnabled(touch_ack_timeout_enabled, |
| 806 touch_ack_timeout_delay_ms_); |
| 807 } |
| 808 |
777 bool InputRouterImpl::IsInOverscrollGesture() const { | 809 bool InputRouterImpl::IsInOverscrollGesture() const { |
778 OverscrollController* controller = client_->GetOverscrollController(); | 810 OverscrollController* controller = client_->GetOverscrollController(); |
779 return controller && controller->overscroll_mode() != OVERSCROLL_NONE; | 811 return controller && controller->overscroll_mode() != OVERSCROLL_NONE; |
780 } | 812 } |
781 | 813 |
782 } // namespace content | 814 } // namespace content |
OLD | NEW |