| 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 11 matching lines...) Expand all Loading... |
| 22 #include "content/common/view_messages.h" | 22 #include "content/common/view_messages.h" |
| 23 #include "content/port/common/input_event_ack_state.h" | 23 #include "content/port/common/input_event_ack_state.h" |
| 24 #include "content/public/browser/notification_service.h" | 24 #include "content/public/browser/notification_service.h" |
| 25 #include "content/public/browser/notification_types.h" | 25 #include "content/public/browser/notification_types.h" |
| 26 #include "content/public/browser/user_metrics.h" | 26 #include "content/public/browser/user_metrics.h" |
| 27 #include "content/public/common/content_switches.h" | 27 #include "content/public/common/content_switches.h" |
| 28 #include "ipc/ipc_sender.h" | 28 #include "ipc/ipc_sender.h" |
| 29 #include "ui/events/event.h" | 29 #include "ui/events/event.h" |
| 30 #include "ui/events/keycodes/keyboard_codes.h" | 30 #include "ui/events/keycodes/keyboard_codes.h" |
| 31 | 31 |
| 32 #if defined(OS_ANDROID) | |
| 33 #include "ui/gfx/android/view_configuration.h" | |
| 34 #include "ui/gfx/screen.h" | |
| 35 #else | |
| 36 #include "ui/events/gestures/gesture_configuration.h" | |
| 37 #endif | |
| 38 | |
| 39 using base::Time; | 32 using base::Time; |
| 40 using base::TimeDelta; | 33 using base::TimeDelta; |
| 41 using base::TimeTicks; | 34 using base::TimeTicks; |
| 42 using blink::WebGestureEvent; | 35 using blink::WebGestureEvent; |
| 43 using blink::WebInputEvent; | 36 using blink::WebInputEvent; |
| 44 using blink::WebKeyboardEvent; | 37 using blink::WebKeyboardEvent; |
| 45 using blink::WebMouseEvent; | 38 using blink::WebMouseEvent; |
| 46 using blink::WebMouseWheelEvent; | 39 using blink::WebMouseWheelEvent; |
| 47 | 40 |
| 48 namespace content { | 41 namespace content { |
| 49 namespace { | 42 namespace { |
| 50 | 43 |
| 51 // TODO(jdduke): Instead of relying on command line flags or conditional | 44 GestureEventWithLatencyInfo MakeGestureEvent(WebInputEvent::Type type, |
| 52 // conditional compilation here, we should instead use an InputRouter::Settings | 45 double timestamp_seconds, |
| 53 // construct, supplied and customized by the RenderWidgetHostView. See | 46 int x, |
| 54 // crbug.com/343917. | 47 int y, |
| 55 bool GetTouchAckTimeoutDelay(base::TimeDelta* touch_ack_timeout_delay) { | 48 int modifiers, |
| 56 CommandLine* parsed_command_line = CommandLine::ForCurrentProcess(); | 49 const ui::LatencyInfo& latency) { |
| 57 if (!parsed_command_line->HasSwitch(switches::kTouchAckTimeoutDelayMs)) | 50 WebGestureEvent result; |
| 58 return false; | |
| 59 | 51 |
| 60 std::string timeout_string = parsed_command_line->GetSwitchValueASCII( | 52 result.type = type; |
| 61 switches::kTouchAckTimeoutDelayMs); | 53 result.x = x; |
| 62 size_t timeout_ms; | 54 result.y = y; |
| 63 if (!base::StringToSizeT(timeout_string, &timeout_ms)) | 55 result.sourceDevice = WebGestureEvent::Touchscreen; |
| 64 return false; | 56 result.timeStampSeconds = timestamp_seconds; |
| 57 result.modifiers = modifiers; |
| 65 | 58 |
| 66 *touch_ack_timeout_delay = base::TimeDelta::FromMilliseconds(timeout_ms); | 59 return GestureEventWithLatencyInfo(result, latency); |
| 67 return true; | |
| 68 } | |
| 69 | |
| 70 #if defined(OS_ANDROID) | |
| 71 double GetTouchMoveSlopSuppressionLengthDips() { | |
| 72 const double touch_slop_length_pixels = | |
| 73 static_cast<double>(gfx::ViewConfiguration::GetTouchSlopInPixels()); | |
| 74 const double device_scale_factor = | |
| 75 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().device_scale_factor(); | |
| 76 return touch_slop_length_pixels / device_scale_factor; | |
| 77 } | |
| 78 #elif defined(USE_AURA) | |
| 79 double GetTouchMoveSlopSuppressionLengthDips() { | |
| 80 return ui::GestureConfiguration::max_touch_move_in_pixels_for_click(); | |
| 81 } | |
| 82 #else | |
| 83 double GetTouchMoveSlopSuppressionLengthDips() { | |
| 84 return 0; | |
| 85 } | |
| 86 #endif | |
| 87 | |
| 88 TouchEventQueue::TouchScrollingMode GetTouchScrollingMode() { | |
| 89 std::string modeString = CommandLine::ForCurrentProcess()-> | |
| 90 GetSwitchValueASCII(switches::kTouchScrollingMode); | |
| 91 if (modeString == switches::kTouchScrollingModeAsyncTouchmove) | |
| 92 return TouchEventQueue::TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE; | |
| 93 if (modeString == switches::kTouchScrollingModeSyncTouchmove) | |
| 94 return TouchEventQueue::TOUCH_SCROLLING_MODE_SYNC_TOUCHMOVE; | |
| 95 if (modeString == switches::kTouchScrollingModeTouchcancel) | |
| 96 return TouchEventQueue::TOUCH_SCROLLING_MODE_TOUCHCANCEL; | |
| 97 if (modeString != "") | |
| 98 LOG(ERROR) << "Invalid --touch-scrolling-mode option: " << modeString; | |
| 99 return TouchEventQueue::TOUCH_SCROLLING_MODE_DEFAULT; | |
| 100 } | 60 } |
| 101 | 61 |
| 102 const char* GetEventAckName(InputEventAckState ack_result) { | 62 const char* GetEventAckName(InputEventAckState ack_result) { |
| 103 switch(ack_result) { | 63 switch(ack_result) { |
| 104 case INPUT_EVENT_ACK_STATE_UNKNOWN: return "UNKNOWN"; | 64 case INPUT_EVENT_ACK_STATE_UNKNOWN: return "UNKNOWN"; |
| 105 case INPUT_EVENT_ACK_STATE_CONSUMED: return "CONSUMED"; | 65 case INPUT_EVENT_ACK_STATE_CONSUMED: return "CONSUMED"; |
| 106 case INPUT_EVENT_ACK_STATE_NOT_CONSUMED: return "NOT_CONSUMED"; | 66 case INPUT_EVENT_ACK_STATE_NOT_CONSUMED: return "NOT_CONSUMED"; |
| 107 case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS: return "NO_CONSUMER_EXISTS"; | 67 case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS: return "NO_CONSUMER_EXISTS"; |
| 108 case INPUT_EVENT_ACK_STATE_IGNORED: return "IGNORED"; | 68 case INPUT_EVENT_ACK_STATE_IGNORED: return "IGNORED"; |
| 109 } | 69 } |
| 110 DLOG(WARNING) << "Unhandled InputEventAckState in GetEventAckName."; | 70 DLOG(WARNING) << "Unhandled InputEventAckState in GetEventAckName."; |
| 111 return ""; | 71 return ""; |
| 112 } | 72 } |
| 113 | 73 |
| 114 } // namespace | 74 } // namespace |
| 115 | 75 |
| 76 InputRouterImpl::Config::Config() { |
| 77 } |
| 78 |
| 116 InputRouterImpl::InputRouterImpl(IPC::Sender* sender, | 79 InputRouterImpl::InputRouterImpl(IPC::Sender* sender, |
| 117 InputRouterClient* client, | 80 InputRouterClient* client, |
| 118 InputAckHandler* ack_handler, | 81 InputAckHandler* ack_handler, |
| 119 int routing_id) | 82 int routing_id, |
| 83 const Config& config) |
| 120 : sender_(sender), | 84 : sender_(sender), |
| 121 client_(client), | 85 client_(client), |
| 122 ack_handler_(ack_handler), | 86 ack_handler_(ack_handler), |
| 123 routing_id_(routing_id), | 87 routing_id_(routing_id), |
| 124 select_range_pending_(false), | 88 select_range_pending_(false), |
| 125 move_caret_pending_(false), | 89 move_caret_pending_(false), |
| 126 mouse_move_pending_(false), | 90 mouse_move_pending_(false), |
| 127 mouse_wheel_pending_(false), | 91 mouse_wheel_pending_(false), |
| 128 touch_ack_timeout_supported_(false), | |
| 129 current_view_flags_(0), | 92 current_view_flags_(0), |
| 130 current_ack_source_(ACK_SOURCE_NONE), | 93 current_ack_source_(ACK_SOURCE_NONE), |
| 131 flush_requested_(false), | 94 flush_requested_(false), |
| 132 touch_event_queue_(this, | 95 touch_event_queue_(this, config.touch_config), |
| 133 GetTouchScrollingMode(), | 96 gesture_event_queue_(this, this, config.gesture_config) { |
| 134 GetTouchMoveSlopSuppressionLengthDips()), | |
| 135 gesture_event_queue_(this, this) { | |
| 136 DCHECK(sender); | 97 DCHECK(sender); |
| 137 DCHECK(client); | 98 DCHECK(client); |
| 138 DCHECK(ack_handler); | 99 DCHECK(ack_handler); |
| 139 touch_ack_timeout_supported_ = | |
| 140 GetTouchAckTimeoutDelay(&touch_ack_timeout_delay_); | |
| 141 UpdateTouchAckTimeoutEnabled(); | 100 UpdateTouchAckTimeoutEnabled(); |
| 142 } | 101 } |
| 143 | 102 |
| 144 InputRouterImpl::~InputRouterImpl() {} | 103 InputRouterImpl::~InputRouterImpl() {} |
| 145 | 104 |
| 146 void InputRouterImpl::Flush() { | 105 void InputRouterImpl::Flush() { |
| 147 flush_requested_ = true; | 106 flush_requested_ = true; |
| 148 SignalFlushedIfNecessary(); | 107 SignalFlushedIfNecessary(); |
| 149 } | 108 } |
| 150 | 109 |
| (...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 696 | 655 |
| 697 OverscrollController* controller = client_->GetOverscrollController(); | 656 OverscrollController* controller = client_->GetOverscrollController(); |
| 698 if (!controller) | 657 if (!controller) |
| 699 return; | 658 return; |
| 700 | 659 |
| 701 controller->ReceivedEventACK( | 660 controller->ReceivedEventACK( |
| 702 event, (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result)); | 661 event, (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result)); |
| 703 } | 662 } |
| 704 | 663 |
| 705 void InputRouterImpl::UpdateTouchAckTimeoutEnabled() { | 664 void InputRouterImpl::UpdateTouchAckTimeoutEnabled() { |
| 706 if (!touch_ack_timeout_supported_) { | |
| 707 touch_event_queue_.SetAckTimeoutEnabled(false, base::TimeDelta()); | |
| 708 return; | |
| 709 } | |
| 710 | |
| 711 // Mobile sites tend to be well-behaved with respect to touch handling, so | 665 // Mobile sites tend to be well-behaved with respect to touch handling, so |
| 712 // they have less need for the touch timeout fallback. | 666 // they have less need for the touch timeout fallback. |
| 713 const bool fixed_page_scale = (current_view_flags_ & FIXED_PAGE_SCALE) != 0; | 667 const bool fixed_page_scale = (current_view_flags_ & FIXED_PAGE_SCALE) != 0; |
| 714 const bool mobile_viewport = (current_view_flags_ & MOBILE_VIEWPORT) != 0; | 668 const bool mobile_viewport = (current_view_flags_ & MOBILE_VIEWPORT) != 0; |
| 715 | 669 |
| 716 // TOUCH_ACTION_NONE will prevent scrolling, in which case the timeout serves | 670 // TOUCH_ACTION_NONE will prevent scrolling, in which case the timeout serves |
| 717 // little purpose. It's also a strong signal that touch handling is critical | 671 // little purpose. It's also a strong signal that touch handling is critical |
| 718 // to page functionality, so the timeout could do more harm than good. | 672 // to page functionality, so the timeout could do more harm than good. |
| 719 const bool touch_action_none = | 673 const bool touch_action_none = |
| 720 touch_action_filter_.allowed_touch_action() == TOUCH_ACTION_NONE; | 674 touch_action_filter_.allowed_touch_action() == TOUCH_ACTION_NONE; |
| 721 | 675 |
| 722 const bool touch_ack_timeout_enabled = !fixed_page_scale && | 676 const bool touch_ack_timeout_enabled = !fixed_page_scale && |
| 723 !mobile_viewport && | 677 !mobile_viewport && |
| 724 !touch_action_none; | 678 !touch_action_none; |
| 725 touch_event_queue_.SetAckTimeoutEnabled(touch_ack_timeout_enabled, | 679 touch_event_queue_.SetAckTimeoutEnabled(touch_ack_timeout_enabled); |
| 726 touch_ack_timeout_delay_); | |
| 727 } | 680 } |
| 728 | 681 |
| 729 void InputRouterImpl::SignalFlushedIfNecessary() { | 682 void InputRouterImpl::SignalFlushedIfNecessary() { |
| 730 if (!flush_requested_) | 683 if (!flush_requested_) |
| 731 return; | 684 return; |
| 732 | 685 |
| 733 if (HasPendingEvents()) | 686 if (HasPendingEvents()) |
| 734 return; | 687 return; |
| 735 | 688 |
| 736 flush_requested_ = false; | 689 flush_requested_ = false; |
| 737 client_->DidFlush(); | 690 client_->DidFlush(); |
| 738 } | 691 } |
| 739 | 692 |
| 740 bool InputRouterImpl::HasPendingEvents() const { | 693 bool InputRouterImpl::HasPendingEvents() const { |
| 741 return !touch_event_queue_.empty() || | 694 return !touch_event_queue_.empty() || |
| 742 !gesture_event_queue_.empty() || | 695 !gesture_event_queue_.empty() || |
| 743 !key_queue_.empty() || | 696 !key_queue_.empty() || |
| 744 mouse_move_pending_ || | 697 mouse_move_pending_ || |
| 745 mouse_wheel_pending_ || | 698 mouse_wheel_pending_ || |
| 746 select_range_pending_ || | 699 select_range_pending_ || |
| 747 move_caret_pending_; | 700 move_caret_pending_; |
| 748 } | 701 } |
| 749 | 702 |
| 750 bool InputRouterImpl::IsInOverscrollGesture() const { | 703 bool InputRouterImpl::IsInOverscrollGesture() const { |
| 751 OverscrollController* controller = client_->GetOverscrollController(); | 704 OverscrollController* controller = client_->GetOverscrollController(); |
| 752 return controller && controller->overscroll_mode() != OVERSCROLL_NONE; | 705 return controller && controller->overscroll_mode() != OVERSCROLL_NONE; |
| 753 } | 706 } |
| 754 | 707 |
| 755 } // namespace content | 708 } // namespace content |
| OLD | NEW |