Chromium Code Reviews| 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 UpdateTouchAckTimeoutEnabled(); | |
| 293 } | |
| 292 | 294 |
| 293 FilterAndSendWebInputEvent(touch_event.event, touch_event.latency, false); | 295 FilterAndSendWebInputEvent(touch_event.event, touch_event.latency, false); |
| 294 } | 296 } |
| 295 | 297 |
| 296 void InputRouterImpl::SendGestureEventImmediately( | 298 void InputRouterImpl::SendGestureEventImmediately( |
| 297 const GestureEventWithLatencyInfo& gesture_event) { | 299 const GestureEventWithLatencyInfo& gesture_event) { |
| 298 FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false); | 300 FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false); |
| 299 } | 301 } |
| 300 | 302 |
| 301 const NativeWebKeyboardEvent* InputRouterImpl::GetLastKeyboardEvent() const { | 303 const NativeWebKeyboardEvent* InputRouterImpl::GetLastKeyboardEvent() const { |
| 302 if (key_queue_.empty()) | 304 if (key_queue_.empty()) |
| 303 return NULL; | 305 return NULL; |
| 304 return &key_queue_.front(); | 306 return &key_queue_.front(); |
| 305 } | 307 } |
| 306 | 308 |
| 307 bool InputRouterImpl::ShouldForwardTouchEvent() const { | 309 bool InputRouterImpl::ShouldForwardTouchEvent() const { |
| 308 // Always send a touch event if the renderer has a touch-event handler. | 310 // Always send a touch event if the renderer has a touch-event handler. |
| 309 return touch_event_queue_->has_handlers(); | 311 return touch_event_queue_->has_handlers(); |
| 310 } | 312 } |
| 311 | 313 |
| 312 void InputRouterImpl::OnViewUpdated(int view_flags) { | 314 void InputRouterImpl::OnViewUpdated(int view_flags) { |
| 313 bool fixed_page_scale = (view_flags & FIXED_PAGE_SCALE) != 0; | 315 current_view_flags_ = view_flags; |
| 314 bool mobile_viewport = (view_flags & MOBILE_VIEWPORT) != 0; | 316 |
| 315 touch_event_queue_->SetAckTimeoutEnabled( | 317 // A fixed page scale or mobile viewport should disable the touch ack timeout. |
| 316 touch_ack_timeout_enabled_ && !(fixed_page_scale || mobile_viewport), | 318 UpdateTouchAckTimeoutEnabled(); |
| 317 touch_ack_timeout_delay_ms_); | |
| 318 } | 319 } |
| 319 | 320 |
| 320 bool InputRouterImpl::OnMessageReceived(const IPC::Message& message) { | 321 bool InputRouterImpl::OnMessageReceived(const IPC::Message& message) { |
| 321 bool handled = true; | 322 bool handled = true; |
| 322 bool message_is_ok = true; | 323 bool message_is_ok = true; |
| 323 IPC_BEGIN_MESSAGE_MAP_EX(InputRouterImpl, message, message_is_ok) | 324 IPC_BEGIN_MESSAGE_MAP_EX(InputRouterImpl, message, message_is_ok) |
| 324 IPC_MESSAGE_HANDLER(InputHostMsg_HandleInputEvent_ACK, OnInputEventAck) | 325 IPC_MESSAGE_HANDLER(InputHostMsg_HandleInputEvent_ACK, OnInputEventAck) |
| 325 IPC_MESSAGE_HANDLER(ViewHostMsg_MoveCaret_ACK, OnMsgMoveCaretAck) | 326 IPC_MESSAGE_HANDLER(ViewHostMsg_MoveCaret_ACK, OnMsgMoveCaretAck) |
| 326 IPC_MESSAGE_HANDLER(ViewHostMsg_SelectRange_ACK, OnSelectRangeAck) | 327 IPC_MESSAGE_HANDLER(ViewHostMsg_SelectRange_ACK, OnSelectRangeAck) |
| 327 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers, | 328 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers, |
| 328 OnHasTouchEventHandlers) | 329 OnHasTouchEventHandlers) |
| 329 IPC_MESSAGE_HANDLER(InputHostMsg_SetTouchAction, | 330 IPC_MESSAGE_HANDLER(InputHostMsg_SetTouchAction, |
| 330 OnSetTouchAction) | 331 OnSetTouchAction) |
| 331 IPC_MESSAGE_UNHANDLED(handled = false) | 332 IPC_MESSAGE_UNHANDLED(handled = false) |
| 332 IPC_END_MESSAGE_MAP() | 333 IPC_END_MESSAGE_MAP() |
| 333 | 334 |
| 334 if (!message_is_ok) | 335 if (!message_is_ok) |
| 335 ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE); | 336 ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE); |
| 336 | 337 |
| 337 return handled; | 338 return handled; |
| 338 } | 339 } |
| 339 | 340 |
| 340 void InputRouterImpl::OnTouchEventAck(const TouchEventWithLatencyInfo& event, | 341 void InputRouterImpl::OnTouchEventAck(const TouchEventWithLatencyInfo& event, |
| 341 InputEventAckState ack_result) { | 342 InputEventAckState ack_result) { |
| 342 // Touchstart events sent to the renderer indicate a new touch sequence, but | 343 // 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. | 344 // in some cases we may filter out sending the touchstart - catch those here. |
| 344 if (WebTouchEventTraits::IsTouchSequenceStart(event.event) && | 345 if (WebTouchEventTraits::IsTouchSequenceStart(event.event) && |
| 345 ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) { | 346 ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) { |
| 346 touch_action_filter_.ResetTouchAction(); | 347 touch_action_filter_.ResetTouchAction(); |
| 348 UpdateTouchAckTimeoutEnabled(); | |
| 347 } | 349 } |
| 348 ack_handler_->OnTouchEventAck(event, ack_result); | 350 ack_handler_->OnTouchEventAck(event, ack_result); |
| 349 } | 351 } |
| 350 | 352 |
| 351 void InputRouterImpl::OnGestureEventAck( | 353 void InputRouterImpl::OnGestureEventAck( |
| 352 const GestureEventWithLatencyInfo& event, | 354 const GestureEventWithLatencyInfo& event, |
| 353 InputEventAckState ack_result) { | 355 InputEventAckState ack_result) { |
| 354 touch_event_queue_->OnGestureEventAck(event, ack_result); | 356 touch_event_queue_->OnGestureEventAck(event, ack_result); |
| 355 ProcessAckForOverscroll(event.event, ack_result); | 357 ProcessAckForOverscroll(event.event, ack_result); |
| 356 ack_handler_->OnGestureEventAck(event, ack_result); | 358 ack_handler_->OnGestureEventAck(event, ack_result); |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 552 } | 554 } |
| 553 | 555 |
| 554 void InputRouterImpl::OnHasTouchEventHandlers(bool has_handlers) { | 556 void InputRouterImpl::OnHasTouchEventHandlers(bool has_handlers) { |
| 555 TRACE_EVENT1("input", "InputRouterImpl::OnHasTouchEventHandlers", | 557 TRACE_EVENT1("input", "InputRouterImpl::OnHasTouchEventHandlers", |
| 556 "has_handlers", has_handlers); | 558 "has_handlers", has_handlers); |
| 557 | 559 |
| 558 touch_event_queue_->OnHasTouchEventHandlers(has_handlers); | 560 touch_event_queue_->OnHasTouchEventHandlers(has_handlers); |
| 559 client_->OnHasTouchEventHandlers(has_handlers); | 561 client_->OnHasTouchEventHandlers(has_handlers); |
| 560 } | 562 } |
| 561 | 563 |
| 562 void InputRouterImpl::OnSetTouchAction( | 564 void InputRouterImpl::OnSetTouchAction(TouchAction touch_action) { |
| 563 content::TouchAction touch_action) { | |
| 564 // Synthetic touchstart events should get filtered out in RenderWidget. | 565 // Synthetic touchstart events should get filtered out in RenderWidget. |
| 565 DCHECK(touch_event_queue_->IsPendingAckTouchStart()); | 566 DCHECK(touch_event_queue_->IsPendingAckTouchStart()); |
| 566 | 567 |
| 567 touch_action_filter_.OnSetTouchAction(touch_action); | 568 touch_action_filter_.OnSetTouchAction(touch_action); |
| 569 | |
| 570 // TOUCH_ACTION_NONE should disable the touch ack timeout. | |
| 571 UpdateTouchAckTimeoutEnabled(); | |
| 568 } | 572 } |
| 569 | 573 |
| 570 void InputRouterImpl::ProcessInputEventAck( | 574 void InputRouterImpl::ProcessInputEventAck( |
| 571 WebInputEvent::Type event_type, | 575 WebInputEvent::Type event_type, |
| 572 InputEventAckState ack_result, | 576 InputEventAckState ack_result, |
| 573 const ui::LatencyInfo& latency_info, | 577 const ui::LatencyInfo& latency_info, |
| 574 AckSource ack_source) { | 578 AckSource ack_source) { |
| 575 TRACE_EVENT2("input", "InputRouterImpl::ProcessInputEventAck", | 579 TRACE_EVENT2("input", "InputRouterImpl::ProcessInputEventAck", |
| 576 "type", WebInputEventTraits::GetName(event_type), | 580 "type", WebInputEventTraits::GetName(event_type), |
| 577 "ack", GetEventAckName(ack_result)); | 581 "ack", GetEventAckName(ack_result)); |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 767 SendGestureEvent(MakeGestureEvent( | 771 SendGestureEvent(MakeGestureEvent( |
| 768 WebInputEvent::GestureScrollEnd, mouse_event.timeStampSeconds, | 772 WebInputEvent::GestureScrollEnd, mouse_event.timeStampSeconds, |
| 769 x, y, 0, event.latency)); | 773 x, y, 0, event.latency)); |
| 770 } | 774 } |
| 771 break; | 775 break; |
| 772 case WebMouseEvent::ButtonNone: | 776 case WebMouseEvent::ButtonNone: |
| 773 break; | 777 break; |
| 774 } | 778 } |
| 775 } | 779 } |
| 776 | 780 |
| 781 void InputRouterImpl::UpdateTouchAckTimeoutEnabled() { | |
| 782 if (!touch_ack_timeout_supported_) { | |
| 783 touch_event_queue_->SetAckTimeoutEnabled(false, 0); | |
| 784 return; | |
| 785 } | |
| 786 | |
| 787 // Mobile sites tend to be well-behaved with respect to touch handling, so | |
| 788 // they have less need for the touch timeout fallback. | |
| 789 const bool fixed_page_scale = (current_view_flags_ & FIXED_PAGE_SCALE) != 0; | |
| 790 const bool mobile_viewport = (current_view_flags_ & MOBILE_VIEWPORT) != 0; | |
| 791 | |
| 792 // TOUCH_ACTION_NONE will prevent scrolling, in which case the timeout serves | |
| 793 // little purpose. It's also a strong signal that touch handling is critical | |
|
Rick Byers
2014/03/05 21:24:23
nit: I believe chromium checkstyle will complain a
jdduke (slow)
2014/03/06 00:15:25
Done.
| |
| 794 // to page functionality, so the timeout could do more harm than good. | |
| 795 const bool touch_action_none = | |
| 796 touch_action_filter_.allowed_touch_action() == TOUCH_ACTION_NONE; | |
| 797 | |
| 798 const bool touch_ack_timeout_enabled = !fixed_page_scale && | |
| 799 !mobile_viewport && | |
| 800 !touch_action_none; | |
| 801 touch_event_queue_->SetAckTimeoutEnabled(touch_ack_timeout_enabled, | |
| 802 touch_ack_timeout_delay_ms_); | |
| 803 } | |
| 804 | |
| 777 bool InputRouterImpl::IsInOverscrollGesture() const { | 805 bool InputRouterImpl::IsInOverscrollGesture() const { |
| 778 OverscrollController* controller = client_->GetOverscrollController(); | 806 OverscrollController* controller = client_->GetOverscrollController(); |
| 779 return controller && controller->overscroll_mode() != OVERSCROLL_NONE; | 807 return controller && controller->overscroll_mode() != OVERSCROLL_NONE; |
| 780 } | 808 } |
| 781 | 809 |
| 782 } // namespace content | 810 } // namespace content |
| OLD | NEW |