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 |