| 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/immediate_input_router.h" | 5 #include "content/browser/renderer_host/input/immediate_input_router.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 "content/browser/renderer_host/input/gesture_event_filter.h" | 10 #include "content/browser/renderer_host/input/base_gesture_event_filter.h" |
| 11 #include "content/browser/renderer_host/input/input_ack_handler.h" | 11 #include "content/browser/renderer_host/input/input_ack_handler.h" |
| 12 #include "content/browser/renderer_host/input/input_router_client.h" | 12 #include "content/browser/renderer_host/input/input_router_client.h" |
| 13 #include "content/browser/renderer_host/input/touch_event_queue.h" | 13 #include "content/browser/renderer_host/input/touch_event_queue.h" |
| 14 #include "content/browser/renderer_host/input/touchpad_tap_suppression_controlle
r.h" | |
| 15 #include "content/browser/renderer_host/overscroll_controller.h" | 14 #include "content/browser/renderer_host/overscroll_controller.h" |
| 16 #include "content/common/content_constants_internal.h" | 15 #include "content/common/content_constants_internal.h" |
| 17 #include "content/common/edit_command.h" | 16 #include "content/common/edit_command.h" |
| 18 #include "content/common/input/web_input_event_traits.h" | 17 #include "content/common/input/web_input_event_traits.h" |
| 19 #include "content/common/input_messages.h" | 18 #include "content/common/input_messages.h" |
| 20 #include "content/common/view_messages.h" | 19 #include "content/common/view_messages.h" |
| 21 #include "content/port/common/input_event_ack_state.h" | 20 #include "content/port/common/input_event_ack_state.h" |
| 22 #include "content/public/browser/notification_service.h" | 21 #include "content/public/browser/notification_service.h" |
| 23 #include "content/public/browser/notification_types.h" | 22 #include "content/public/browser/notification_types.h" |
| 24 #include "content/public/browser/user_metrics.h" | 23 #include "content/public/browser/user_metrics.h" |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 case INPUT_EVENT_ACK_STATE_CONSUMED: return "CONSUMED"; | 62 case INPUT_EVENT_ACK_STATE_CONSUMED: return "CONSUMED"; |
| 64 case INPUT_EVENT_ACK_STATE_NOT_CONSUMED: return "NOT_CONSUMED"; | 63 case INPUT_EVENT_ACK_STATE_NOT_CONSUMED: return "NOT_CONSUMED"; |
| 65 case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS: return "NO_CONSUMER_EXISTS"; | 64 case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS: return "NO_CONSUMER_EXISTS"; |
| 66 default: | 65 default: |
| 67 DLOG(WARNING) << "Unhandled InputEventAckState in GetEventAckName.\n"; | 66 DLOG(WARNING) << "Unhandled InputEventAckState in GetEventAckName.\n"; |
| 68 break; | 67 break; |
| 69 } | 68 } |
| 70 return ""; | 69 return ""; |
| 71 } | 70 } |
| 72 | 71 |
| 73 bool BrowserSideFlingEnabled() { | |
| 74 return CommandLine::ForCurrentProcess()->HasSwitch( | |
| 75 switches::kEnableBrowserSideFling); | |
| 76 } | |
| 77 | |
| 78 } // namespace | 72 } // namespace |
| 79 | 73 |
| 80 // A helper class that based on the value of the |kEnableBrowserSideFling| flag | |
| 81 // does event filtering using either |BaseGestureEventFilter| or | |
| 82 // |GestureEventFilter|. | |
| 83 class ImmediateInputRouter::EventFilteringHelper { | |
| 84 public: | |
| 85 // |router| must outlive us. | |
| 86 explicit EventFilteringHelper(ImmediateInputRouter* router) { | |
| 87 if (BrowserSideFlingEnabled()) | |
| 88 gesture_event_filter_.reset(new BaseGestureEventFilter(router)); | |
| 89 else | |
| 90 gesture_event_filter_.reset(new GestureEventFilter(router, router)); | |
| 91 } | |
| 92 virtual ~EventFilteringHelper() {} | |
| 93 | |
| 94 bool ShouldDeferMouseDown(const MouseEventWithLatencyInfo& mouse_event) { | |
| 95 if (BrowserSideFlingEnabled()) | |
| 96 return false; | |
| 97 | |
| 98 return static_cast<GestureEventFilter*>(gesture_event_filter_.get())-> | |
| 99 GetTouchpadTapSuppressionController()->ShouldDeferMouseDown( | |
| 100 mouse_event); | |
| 101 } | |
| 102 | |
| 103 bool ShouldDeferMouseUp(const MouseEventWithLatencyInfo& mouse_event) { | |
| 104 if (BrowserSideFlingEnabled()) | |
| 105 return false; | |
| 106 | |
| 107 return static_cast<GestureEventFilter*>(gesture_event_filter_.get())-> | |
| 108 GetTouchpadTapSuppressionController()->ShouldSuppressMouseUp(); | |
| 109 } | |
| 110 | |
| 111 void FlingHasBeenHalted() { | |
| 112 if (BrowserSideFlingEnabled()) | |
| 113 return; | |
| 114 | |
| 115 static_cast<GestureEventFilter*>(gesture_event_filter_.get())-> | |
| 116 FlingHasBeenHalted(); | |
| 117 } | |
| 118 | |
| 119 bool ShouldForwardGesture(const GestureEventWithLatencyInfo& gesture_event) { | |
| 120 return gesture_event_filter_->ShouldForward(gesture_event); | |
| 121 } | |
| 122 | |
| 123 bool HasQueuedGestureEvents() { | |
| 124 return gesture_event_filter_->HasQueuedGestureEvents(); | |
| 125 } | |
| 126 | |
| 127 void ProcessGestureAck(InputEventAckState ack_result, | |
| 128 WebKit::WebInputEvent::Type type, | |
| 129 const ui::LatencyInfo& latency) { | |
| 130 gesture_event_filter_->ProcessGestureAck(ack_result, type, latency); | |
| 131 } | |
| 132 | |
| 133 private: | |
| 134 friend class ImmediateInputRouter; | |
| 135 scoped_ptr<BaseGestureEventFilter> gesture_event_filter_; | |
| 136 | |
| 137 DISALLOW_COPY_AND_ASSIGN(EventFilteringHelper); | |
| 138 }; | |
| 139 | |
| 140 ImmediateInputRouter::ImmediateInputRouter(IPC::Sender* sender, | 74 ImmediateInputRouter::ImmediateInputRouter(IPC::Sender* sender, |
| 141 InputRouterClient* client, | 75 InputRouterClient* client, |
| 142 InputAckHandler* ack_handler, | 76 InputAckHandler* ack_handler, |
| 143 int routing_id) | 77 int routing_id) |
| 144 : sender_(sender), | 78 : sender_(sender), |
| 145 client_(client), | 79 client_(client), |
| 146 ack_handler_(ack_handler), | 80 ack_handler_(ack_handler), |
| 147 routing_id_(routing_id), | 81 routing_id_(routing_id), |
| 148 select_range_pending_(false), | 82 select_range_pending_(false), |
| 149 move_caret_pending_(false), | 83 move_caret_pending_(false), |
| 150 mouse_move_pending_(false), | 84 mouse_move_pending_(false), |
| 151 mouse_wheel_pending_(false), | 85 mouse_wheel_pending_(false), |
| 152 has_touch_handler_(false), | 86 has_touch_handler_(false), |
| 153 current_ack_source_(ACK_SOURCE_NONE), | 87 current_ack_source_(ACK_SOURCE_NONE), |
| 154 touch_event_queue_(new TouchEventQueue(this)), | 88 touch_event_queue_(new TouchEventQueue(this)), |
| 155 flinger_(new Flinger(this)), | 89 flinger_(new Flinger(this)), |
| 156 event_filter_(new EventFilteringHelper(this)) { | 90 event_filter_(new BaseGestureEventFilter(this)) { |
| 157 DCHECK(sender); | 91 DCHECK(sender); |
| 158 DCHECK(client); | 92 DCHECK(client); |
| 159 DCHECK(ack_handler); | 93 DCHECK(ack_handler); |
| 160 } | 94 } |
| 161 | 95 |
| 162 ImmediateInputRouter::~ImmediateInputRouter() { | 96 ImmediateInputRouter::~ImmediateInputRouter() { |
| 163 } | 97 } |
| 164 | 98 |
| 165 void ImmediateInputRouter::Flush() { | 99 void ImmediateInputRouter::Flush() { |
| 166 NOTREACHED() << "ImmediateInputRouter will never request a flush."; | 100 NOTREACHED() << "ImmediateInputRouter will never request a flush."; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 178 NOTREACHED() << "WebInputEvents should never be sent via SendInput."; | 112 NOTREACHED() << "WebInputEvents should never be sent via SendInput."; |
| 179 return false; | 113 return false; |
| 180 default: | 114 default: |
| 181 return Send(message.release()); | 115 return Send(message.release()); |
| 182 } | 116 } |
| 183 } | 117 } |
| 184 | 118 |
| 185 void ImmediateInputRouter::SendMouseEvent( | 119 void ImmediateInputRouter::SendMouseEvent( |
| 186 const MouseEventWithLatencyInfo& mouse_event) { | 120 const MouseEventWithLatencyInfo& mouse_event) { |
| 187 // Order is important here; we need to convert all MouseEvents before they | 121 // Order is important here; we need to convert all MouseEvents before they |
| 188 // propagate further, e.g., to the tap suppression controller. | 122 // propagate further. |
| 189 if (CommandLine::ForCurrentProcess()->HasSwitch( | 123 if (CommandLine::ForCurrentProcess()->HasSwitch( |
| 190 switches::kSimulateTouchScreenWithMouse)) { | 124 switches::kSimulateTouchScreenWithMouse)) { |
| 191 SimulateTouchGestureWithMouse(mouse_event); | 125 SimulateTouchGestureWithMouse(mouse_event); |
| 192 return; | 126 return; |
| 193 } | 127 } |
| 194 | 128 |
| 195 if (BrowserSideFlingEnabled() && flinger_->HandleMouseEvent(mouse_event)) | 129 if (flinger_->HandleMouseEvent(mouse_event)) |
| 196 return; | 130 return; |
| 197 | 131 |
| 198 if (mouse_event.event.type == WebInputEvent::MouseDown && | |
| 199 event_filter_->ShouldDeferMouseDown(mouse_event)) | |
| 200 return; | |
| 201 if (mouse_event.event.type == WebInputEvent::MouseUp && | |
| 202 event_filter_->ShouldDeferMouseUp(mouse_event)) | |
| 203 return; | |
| 204 | |
| 205 SendMouseEventImmediately(mouse_event); | 132 SendMouseEventImmediately(mouse_event); |
| 206 } | 133 } |
| 207 | 134 |
| 208 void ImmediateInputRouter::SendWheelEvent( | 135 void ImmediateInputRouter::SendWheelEvent( |
| 209 const MouseWheelEventWithLatencyInfo& wheel_event) { | 136 const MouseWheelEventWithLatencyInfo& wheel_event) { |
| 210 if (BrowserSideFlingEnabled() && flinger_->HandleWheelEvent(wheel_event)) | 137 if (flinger_->HandleWheelEvent(wheel_event)) |
| 211 return; | 138 return; |
| 212 | 139 |
| 213 // If there's already a mouse wheel event waiting to be sent to the renderer, | 140 // If there's already a mouse wheel event waiting to be sent to the renderer, |
| 214 // add the new deltas to that event. Not doing so (e.g., by dropping the old | 141 // add the new deltas to that event. Not doing so (e.g., by dropping the old |
| 215 // event, as for mouse moves) results in very slow scrolling on the Mac (on | 142 // event, as for mouse moves) results in very slow scrolling on the Mac (on |
| 216 // which many, very small wheel events are sent). | 143 // which many, very small wheel events are sent). |
| 217 if (mouse_wheel_pending_) { | 144 if (mouse_wheel_pending_) { |
| 218 if (coalesced_mouse_wheel_events_.empty() || | 145 if (coalesced_mouse_wheel_events_.empty() || |
| 219 !coalesced_mouse_wheel_events_.back().CanCoalesceWith(wheel_event)) { | 146 !coalesced_mouse_wheel_events_.back().CanCoalesceWith(wheel_event)) { |
| 220 coalesced_mouse_wheel_events_.push_back(wheel_event); | 147 coalesced_mouse_wheel_events_.push_back(wheel_event); |
| 221 } else { | 148 } else { |
| 222 coalesced_mouse_wheel_events_.back().CoalesceWith(wheel_event); | 149 coalesced_mouse_wheel_events_.back().CoalesceWith(wheel_event); |
| 223 } | 150 } |
| 224 return; | 151 return; |
| 225 } | 152 } |
| 226 mouse_wheel_pending_ = true; | 153 mouse_wheel_pending_ = true; |
| 227 current_wheel_event_ = wheel_event; | 154 current_wheel_event_ = wheel_event; |
| 228 | 155 |
| 229 HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize", | 156 HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize", |
| 230 coalesced_mouse_wheel_events_.size()); | 157 coalesced_mouse_wheel_events_.size()); |
| 231 | 158 |
| 232 FilterAndSendWebInputEvent(wheel_event.event, wheel_event.latency, false); | 159 FilterAndSendWebInputEvent(wheel_event.event, wheel_event.latency, false); |
| 233 } | 160 } |
| 234 | 161 |
| 235 void ImmediateInputRouter::SendKeyboardEvent( | 162 void ImmediateInputRouter::SendKeyboardEvent( |
| 236 const NativeWebKeyboardEvent& key_event, | 163 const NativeWebKeyboardEvent& key_event, |
| 237 const ui::LatencyInfo& latency_info, | 164 const ui::LatencyInfo& latency_info, |
| 238 bool is_keyboard_shortcut) { | 165 bool is_keyboard_shortcut) { |
| 239 if (BrowserSideFlingEnabled() && flinger_->HandleKeyboardEvent()) | 166 if (flinger_->HandleKeyboardEvent()) |
| 240 return; | 167 return; |
| 241 | 168 |
| 242 // Put all WebKeyboardEvent objects in a queue since we can't trust the | 169 // Put all WebKeyboardEvent objects in a queue since we can't trust the |
| 243 // renderer and we need to give something to the HandleKeyboardEvent | 170 // renderer and we need to give something to the HandleKeyboardEvent |
| 244 // handler. | 171 // handler. |
| 245 key_queue_.push_back(key_event); | 172 key_queue_.push_back(key_event); |
| 246 HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size()); | 173 HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size()); |
| 247 | 174 |
| 248 event_filter_->FlingHasBeenHalted(); | |
| 249 | |
| 250 // Only forward the non-native portions of our event. | 175 // Only forward the non-native portions of our event. |
| 251 FilterAndSendWebInputEvent(key_event, latency_info, is_keyboard_shortcut); | 176 FilterAndSendWebInputEvent(key_event, latency_info, is_keyboard_shortcut); |
| 252 } | 177 } |
| 253 | 178 |
| 254 void ImmediateInputRouter::SendGestureEvent( | 179 void ImmediateInputRouter::SendGestureEvent( |
| 255 const GestureEventWithLatencyInfo& gesture_event) { | 180 const GestureEventWithLatencyInfo& gesture_event) { |
| 256 HandleGestureScroll(gesture_event); | 181 HandleGestureScroll(gesture_event); |
| 257 | 182 |
| 258 if (BrowserSideFlingEnabled() && flinger_->HandleGestureEvent(gesture_event)) | 183 if (flinger_->HandleGestureEvent(gesture_event)) |
| 259 return; | 184 return; |
| 260 | 185 |
| 261 if (!IsInOverscrollGesture() && | 186 if (!IsInOverscrollGesture() && |
| 262 !event_filter_->ShouldForwardGesture(gesture_event)) { | 187 !event_filter_->ShouldForward(gesture_event)) { |
| 263 OverscrollController* controller = client_->GetOverscrollController(); | 188 OverscrollController* controller = client_->GetOverscrollController(); |
| 264 if (controller) | 189 if (controller) |
| 265 controller->DiscardingGestureEvent(gesture_event.event); | 190 controller->DiscardingGestureEvent(gesture_event.event); |
| 266 return; | 191 return; |
| 267 } | 192 } |
| 268 | 193 |
| 269 FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false); | 194 FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false); |
| 270 } | 195 } |
| 271 | 196 |
| 272 void ImmediateInputRouter::SendTouchEvent( | 197 void ImmediateInputRouter::SendTouchEvent( |
| 273 const TouchEventWithLatencyInfo& touch_event) { | 198 const TouchEventWithLatencyInfo& touch_event) { |
| 274 touch_event_queue_->QueueEvent(touch_event); | 199 touch_event_queue_->QueueEvent(touch_event); |
| 275 } | 200 } |
| 276 | 201 |
| 277 // Forwards MouseEvent without passing it through | |
| 278 // TouchpadTapSuppressionController. | |
| 279 void ImmediateInputRouter::SendMouseEventImmediately( | 202 void ImmediateInputRouter::SendMouseEventImmediately( |
| 280 const MouseEventWithLatencyInfo& mouse_event) { | 203 const MouseEventWithLatencyInfo& mouse_event) { |
| 281 // Avoid spamming the renderer with mouse move events. It is important | 204 // Avoid spamming the renderer with mouse move events. It is important |
| 282 // to note that WM_MOUSEMOVE events are anyways synthetic, but since our | 205 // to note that WM_MOUSEMOVE events are anyways synthetic, but since our |
| 283 // thread is able to rapidly consume WM_MOUSEMOVE events, we may get way | 206 // thread is able to rapidly consume WM_MOUSEMOVE events, we may get way |
| 284 // more WM_MOUSEMOVE events than we wish to send to the renderer. | 207 // more WM_MOUSEMOVE events than we wish to send to the renderer. |
| 285 if (mouse_event.event.type == WebInputEvent::MouseMove) { | 208 if (mouse_event.event.type == WebInputEvent::MouseMove) { |
| 286 if (mouse_move_pending_) { | 209 if (mouse_move_pending_) { |
| 287 if (!next_mouse_move_) | 210 if (!next_mouse_move_) |
| 288 next_mouse_move_.reset(new MouseEventWithLatencyInfo(mouse_event)); | 211 next_mouse_move_.reset(new MouseEventWithLatencyInfo(mouse_event)); |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 451 OverscrollController::Disposition disposition = | 374 OverscrollController::Disposition disposition = |
| 452 controller->DispatchEvent(input_event, latency_info); | 375 controller->DispatchEvent(input_event, latency_info); |
| 453 | 376 |
| 454 bool consumed = disposition == OverscrollController::CONSUMED; | 377 bool consumed = disposition == OverscrollController::CONSUMED; |
| 455 | 378 |
| 456 if (disposition == OverscrollController::SHOULD_FORWARD_TO_GESTURE_FILTER) { | 379 if (disposition == OverscrollController::SHOULD_FORWARD_TO_GESTURE_FILTER) { |
| 457 DCHECK(WebInputEvent::isGestureEventType(input_event.type)); | 380 DCHECK(WebInputEvent::isGestureEventType(input_event.type)); |
| 458 const WebKit::WebGestureEvent& gesture_event = | 381 const WebKit::WebGestureEvent& gesture_event = |
| 459 static_cast<const WebKit::WebGestureEvent&>(input_event); | 382 static_cast<const WebKit::WebGestureEvent&>(input_event); |
| 460 // An ACK is expected for the event, so mark it as consumed. | 383 // An ACK is expected for the event, so mark it as consumed. |
| 461 consumed = !event_filter_->ShouldForwardGesture( | 384 consumed = !event_filter_->ShouldForward( |
| 462 GestureEventWithLatencyInfo(gesture_event, latency_info)); | 385 GestureEventWithLatencyInfo(gesture_event, latency_info)); |
| 463 } | 386 } |
| 464 | 387 |
| 465 if (consumed) { | 388 if (consumed) { |
| 466 InputEventAckState overscroll_ack = | 389 InputEventAckState overscroll_ack = |
| 467 WebInputEvent::isTouchEventType(input_event.type) ? | 390 WebInputEvent::isTouchEventType(input_event.type) ? |
| 468 INPUT_EVENT_ACK_STATE_NOT_CONSUMED : INPUT_EVENT_ACK_STATE_CONSUMED; | 391 INPUT_EVENT_ACK_STATE_NOT_CONSUMED : INPUT_EVENT_ACK_STATE_CONSUMED; |
| 469 ProcessInputEventAck(input_event.type, | 392 ProcessInputEventAck(input_event.type, |
| 470 overscroll_ack, | 393 overscroll_ack, |
| 471 latency_info, | 394 latency_info, |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 769 case WebMouseEvent::ButtonNone: | 692 case WebMouseEvent::ButtonNone: |
| 770 break; | 693 break; |
| 771 } | 694 } |
| 772 } | 695 } |
| 773 | 696 |
| 774 bool ImmediateInputRouter::IsInOverscrollGesture() const { | 697 bool ImmediateInputRouter::IsInOverscrollGesture() const { |
| 775 OverscrollController* controller = client_->GetOverscrollController(); | 698 OverscrollController* controller = client_->GetOverscrollController(); |
| 776 return controller && controller->overscroll_mode() != OVERSCROLL_NONE; | 699 return controller && controller->overscroll_mode() != OVERSCROLL_NONE; |
| 777 } | 700 } |
| 778 | 701 |
| 779 BaseGestureEventFilter* ImmediateInputRouter::gesture_event_filter() { | |
| 780 return event_filter_->gesture_event_filter_.get(); | |
| 781 } | |
| 782 | |
| 783 } // namespace content | 702 } // namespace content |
| OLD | NEW |