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/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" | 14 #include "content/browser/renderer_host/input/touchpad_tap_suppression_controlle
r.h" |
15 #include "content/browser/renderer_host/overscroll_controller.h" | 15 #include "content/browser/renderer_host/overscroll_controller.h" |
16 #include "content/common/content_constants_internal.h" | 16 #include "content/common/content_constants_internal.h" |
17 #include "content/common/edit_command.h" | 17 #include "content/common/edit_command.h" |
18 #include "content/common/input/web_input_event_traits.h" | 18 #include "content/common/input/web_input_event_traits.h" |
19 #include "content/common/input_messages.h" | 19 #include "content/common/input_messages.h" |
20 #include "content/common/view_messages.h" | 20 #include "content/common/view_messages.h" |
21 #include "content/port/common/input_event_ack_state.h" | 21 #include "content/port/common/input_event_ack_state.h" |
22 #include "content/public/browser/notification_service.h" | 22 #include "content/public/browser/notification_service.h" |
23 #include "content/public/browser/notification_types.h" | 23 #include "content/public/browser/notification_types.h" |
24 #include "content/public/browser/user_metrics.h" | 24 #include "content/public/browser/user_metrics.h" |
25 #include "content/public/common/content_switches.h" | 25 #include "content/public/common/content_switches.h" |
| 26 #include "content/public/common/touch_action.h" |
26 #include "ipc/ipc_sender.h" | 27 #include "ipc/ipc_sender.h" |
27 #include "ui/events/event.h" | 28 #include "ui/events/event.h" |
28 #include "ui/events/keycodes/keyboard_codes.h" | 29 #include "ui/events/keycodes/keyboard_codes.h" |
29 | 30 |
30 using base::Time; | 31 using base::Time; |
31 using base::TimeDelta; | 32 using base::TimeDelta; |
32 using base::TimeTicks; | 33 using base::TimeTicks; |
33 using WebKit::WebGestureEvent; | 34 using WebKit::WebGestureEvent; |
34 using WebKit::WebInputEvent; | 35 using WebKit::WebInputEvent; |
35 using WebKit::WebKeyboardEvent; | 36 using WebKit::WebKeyboardEvent; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 int routing_id) | 79 int routing_id) |
79 : sender_(sender), | 80 : sender_(sender), |
80 client_(client), | 81 client_(client), |
81 ack_handler_(ack_handler), | 82 ack_handler_(ack_handler), |
82 routing_id_(routing_id), | 83 routing_id_(routing_id), |
83 select_range_pending_(false), | 84 select_range_pending_(false), |
84 move_caret_pending_(false), | 85 move_caret_pending_(false), |
85 mouse_move_pending_(false), | 86 mouse_move_pending_(false), |
86 mouse_wheel_pending_(false), | 87 mouse_wheel_pending_(false), |
87 has_touch_handler_(false), | 88 has_touch_handler_(false), |
| 89 drop_scroll_gesture_events_(false), |
| 90 allowed_touch_action_(content::TOUCH_ACTION_AUTO), |
88 current_ack_source_(ACK_SOURCE_NONE), | 91 current_ack_source_(ACK_SOURCE_NONE), |
89 touch_event_queue_(new TouchEventQueue(this)), | 92 touch_event_queue_(new TouchEventQueue(this)), |
90 gesture_event_filter_(new GestureEventFilter(this, this)) { | 93 gesture_event_filter_(new GestureEventFilter(this, this)) { |
91 DCHECK(sender); | 94 DCHECK(sender); |
92 DCHECK(client); | 95 DCHECK(client); |
93 DCHECK(ack_handler); | 96 DCHECK(ack_handler); |
94 } | 97 } |
95 | 98 |
96 ImmediateInputRouter::~ImmediateInputRouter() { | 99 ImmediateInputRouter::~ImmediateInputRouter() { |
97 } | 100 } |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size()); | 176 HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size()); |
174 | 177 |
175 gesture_event_filter_->FlingHasBeenHalted(); | 178 gesture_event_filter_->FlingHasBeenHalted(); |
176 | 179 |
177 // Only forward the non-native portions of our event. | 180 // Only forward the non-native portions of our event. |
178 FilterAndSendWebInputEvent(key_event, latency_info, is_keyboard_shortcut); | 181 FilterAndSendWebInputEvent(key_event, latency_info, is_keyboard_shortcut); |
179 } | 182 } |
180 | 183 |
181 void ImmediateInputRouter::SendGestureEvent( | 184 void ImmediateInputRouter::SendGestureEvent( |
182 const GestureEventWithLatencyInfo& gesture_event) { | 185 const GestureEventWithLatencyInfo& gesture_event) { |
183 HandleGestureScroll(gesture_event); | 186 if (FilterTouchAction(gesture_event)) |
| 187 return; |
184 | 188 |
185 if (!IsInOverscrollGesture() && | 189 if (!IsInOverscrollGesture() && |
186 !gesture_event_filter_->ShouldForward(gesture_event)) { | 190 !gesture_event_filter_->ShouldForward(gesture_event)) { |
187 OverscrollController* controller = client_->GetOverscrollController(); | 191 OverscrollController* controller = client_->GetOverscrollController(); |
188 if (controller) | 192 if (controller) |
189 controller->DiscardingGestureEvent(gesture_event.event); | 193 controller->DiscardingGestureEvent(gesture_event.event); |
190 return; | 194 return; |
191 } | 195 } |
192 | 196 |
193 FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false); | 197 FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false); |
(...skipping 26 matching lines...) Expand all Loading... |
220 FilterAndSendWebInputEvent(mouse_event.event, mouse_event.latency, false); | 224 FilterAndSendWebInputEvent(mouse_event.event, mouse_event.latency, false); |
221 } | 225 } |
222 | 226 |
223 void ImmediateInputRouter::SendTouchEventImmediately( | 227 void ImmediateInputRouter::SendTouchEventImmediately( |
224 const TouchEventWithLatencyInfo& touch_event) { | 228 const TouchEventWithLatencyInfo& touch_event) { |
225 FilterAndSendWebInputEvent(touch_event.event, touch_event.latency, false); | 229 FilterAndSendWebInputEvent(touch_event.event, touch_event.latency, false); |
226 } | 230 } |
227 | 231 |
228 void ImmediateInputRouter::SendGestureEventImmediately( | 232 void ImmediateInputRouter::SendGestureEventImmediately( |
229 const GestureEventWithLatencyInfo& gesture_event) { | 233 const GestureEventWithLatencyInfo& gesture_event) { |
230 HandleGestureScroll(gesture_event); | 234 if (FilterTouchAction(gesture_event)) |
| 235 return; |
231 FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false); | 236 FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false); |
232 } | 237 } |
233 | 238 |
234 const NativeWebKeyboardEvent* | 239 const NativeWebKeyboardEvent* |
235 ImmediateInputRouter::GetLastKeyboardEvent() const { | 240 ImmediateInputRouter::GetLastKeyboardEvent() const { |
236 if (key_queue_.empty()) | 241 if (key_queue_.empty()) |
237 return NULL; | 242 return NULL; |
238 return &key_queue_.front(); | 243 return &key_queue_.front(); |
239 } | 244 } |
240 | 245 |
241 bool ImmediateInputRouter::ShouldForwardTouchEvent() const { | 246 bool ImmediateInputRouter::ShouldForwardTouchEvent() const { |
242 // Always send a touch event if the renderer has a touch-event handler. It is | 247 // Always send a touch event if the renderer has a touch-event handler. It is |
243 // possible that a renderer stops listening to touch-events while there are | 248 // possible that a renderer stops listening to touch-events while there are |
244 // still events in the touch-queue. In such cases, the new events should still | 249 // still events in the touch-queue. In such cases, the new events should still |
245 // get into the queue. | 250 // get into the queue. |
246 return has_touch_handler_ || !touch_event_queue_->empty(); | 251 return has_touch_handler_ || !touch_event_queue_->empty(); |
247 } | 252 } |
248 | 253 |
249 bool ImmediateInputRouter::OnMessageReceived(const IPC::Message& message) { | 254 bool ImmediateInputRouter::OnMessageReceived(const IPC::Message& message) { |
250 bool handled = true; | 255 bool handled = true; |
251 bool message_is_ok = true; | 256 bool message_is_ok = true; |
252 IPC_BEGIN_MESSAGE_MAP_EX(ImmediateInputRouter, message, message_is_ok) | 257 IPC_BEGIN_MESSAGE_MAP_EX(ImmediateInputRouter, message, message_is_ok) |
253 IPC_MESSAGE_HANDLER(InputHostMsg_HandleInputEvent_ACK, OnInputEventAck) | 258 IPC_MESSAGE_HANDLER(InputHostMsg_HandleInputEvent_ACK, OnInputEventAck) |
254 IPC_MESSAGE_HANDLER(ViewHostMsg_MoveCaret_ACK, OnMsgMoveCaretAck) | 259 IPC_MESSAGE_HANDLER(ViewHostMsg_MoveCaret_ACK, OnMsgMoveCaretAck) |
255 IPC_MESSAGE_HANDLER(ViewHostMsg_SelectRange_ACK, OnSelectRangeAck) | 260 IPC_MESSAGE_HANDLER(ViewHostMsg_SelectRange_ACK, OnSelectRangeAck) |
256 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers, | 261 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers, |
257 OnHasTouchEventHandlers) | 262 OnHasTouchEventHandlers) |
| 263 IPC_MESSAGE_HANDLER(ViewHostMsg_SetTouchAction, |
| 264 OnSetTouchAction) |
258 IPC_MESSAGE_UNHANDLED(handled = false) | 265 IPC_MESSAGE_UNHANDLED(handled = false) |
259 IPC_END_MESSAGE_MAP() | 266 IPC_END_MESSAGE_MAP() |
260 | 267 |
261 if (!message_is_ok) | 268 if (!message_is_ok) |
262 ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE); | 269 ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE); |
263 | 270 |
264 return handled; | 271 return handled; |
265 } | 272 } |
266 | 273 |
267 void ImmediateInputRouter::OnTouchEventAck( | 274 void ImmediateInputRouter::OnTouchEventAck( |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
455 | 462 |
456 void ImmediateInputRouter::OnHasTouchEventHandlers(bool has_handlers) { | 463 void ImmediateInputRouter::OnHasTouchEventHandlers(bool has_handlers) { |
457 if (has_touch_handler_ == has_handlers) | 464 if (has_touch_handler_ == has_handlers) |
458 return; | 465 return; |
459 has_touch_handler_ = has_handlers; | 466 has_touch_handler_ = has_handlers; |
460 if (!has_handlers) | 467 if (!has_handlers) |
461 touch_event_queue_->FlushQueue(); | 468 touch_event_queue_->FlushQueue(); |
462 client_->OnHasTouchEventHandlers(has_handlers); | 469 client_->OnHasTouchEventHandlers(has_handlers); |
463 } | 470 } |
464 | 471 |
| 472 void ImmediateInputRouter::OnSetTouchAction( |
| 473 int touch_id, |
| 474 content::TouchAction touchAction) |
| 475 { |
| 476 // Don't process touch-action messages for synthetic touches we know |
| 477 // nothing about. |
| 478 if (!touch_event_queue_->IsTouchStartPendingAck(touch_id)) |
| 479 return; |
| 480 |
| 481 // For multiple fingers, we take the intersection of the touch actions for |
| 482 // all fingers that have gone down during this action. |
| 483 // TODO(rbyers): Get some agreed upon multi-finger semantic for touch-action |
| 484 // included in the pointer events specification. crbug.com/241964 |
| 485 if (touchAction == content::TOUCH_ACTION_NONE) |
| 486 allowed_touch_action_ = content::TOUCH_ACTION_NONE; |
| 487 } |
| 488 |
465 void ImmediateInputRouter::ProcessInputEventAck( | 489 void ImmediateInputRouter::ProcessInputEventAck( |
466 WebInputEvent::Type event_type, | 490 WebInputEvent::Type event_type, |
467 InputEventAckState ack_result, | 491 InputEventAckState ack_result, |
468 const ui::LatencyInfo& latency_info, | 492 const ui::LatencyInfo& latency_info, |
469 AckSource ack_source) { | 493 AckSource ack_source) { |
470 TRACE_EVENT2("input", "ImmediateInputRouter::ProcessInputEventAck", | 494 TRACE_EVENT2("input", "ImmediateInputRouter::ProcessInputEventAck", |
471 "type", WebInputEventTraits::GetName(event_type), | 495 "type", WebInputEventTraits::GetName(event_type), |
472 "ack", GetEventAckName(ack_result)); | 496 "ack", GetEventAckName(ack_result)); |
473 | 497 |
474 // Note: The keyboard ack must be treated carefully, as it may result in | 498 // Note: The keyboard ack must be treated carefully, as it may result in |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
584 return; | 608 return; |
585 | 609 |
586 OverscrollController* controller = client_->GetOverscrollController(); | 610 OverscrollController* controller = client_->GetOverscrollController(); |
587 if (!controller) | 611 if (!controller) |
588 return; | 612 return; |
589 | 613 |
590 controller->ReceivedEventACK( | 614 controller->ReceivedEventACK( |
591 event, (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result)); | 615 event, (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result)); |
592 } | 616 } |
593 | 617 |
594 void ImmediateInputRouter::HandleGestureScroll( | 618 bool ImmediateInputRouter::FilterTouchAction( |
595 const GestureEventWithLatencyInfo& gesture_event) { | 619 const GestureEventWithLatencyInfo& gesture_event) { |
| 620 |
| 621 // Filter for allowable touch actions first (eg. before the TouchEventQueue |
| 622 // can decide to send a touch cancel event). |
| 623 // TODO: Does this belong in GestureEventFilter, even though the filtering |
| 624 // happens at a different stage from the other filters there? |
| 625 // TODO(rbyers): Add touch-action control over for pinch. crbug.com/247566. |
| 626 switch(gesture_event.event.type) { |
| 627 case WebInputEvent::GestureScrollBegin: |
| 628 if (allowed_touch_action_ == TOUCH_ACTION_NONE) |
| 629 drop_scroll_gesture_events_ = true; |
| 630 // FALL THROUGH |
| 631 case WebInputEvent::GestureScrollUpdate: |
| 632 case WebInputEvent::GestureScrollUpdateWithoutPropagation: |
| 633 if (drop_scroll_gesture_events_) |
| 634 return true; |
| 635 break; |
| 636 |
| 637 case WebInputEvent::GestureScrollEnd: |
| 638 case WebInputEvent::GestureFlingStart: |
| 639 allowed_touch_action_ = content::TOUCH_ACTION_AUTO; |
| 640 if (drop_scroll_gesture_events_) { |
| 641 drop_scroll_gesture_events_ = false; |
| 642 return true; |
| 643 } |
| 644 break; |
| 645 |
| 646 default: |
| 647 break; |
| 648 } |
| 649 |
| 650 // This touch action is permitted, allow it to cancel in-progress touches. |
596 touch_event_queue_->OnGestureScrollEvent(gesture_event); | 651 touch_event_queue_->OnGestureScrollEvent(gesture_event); |
| 652 return false; |
597 } | 653 } |
598 | 654 |
599 void ImmediateInputRouter::SimulateTouchGestureWithMouse( | 655 void ImmediateInputRouter::SimulateTouchGestureWithMouse( |
600 const MouseEventWithLatencyInfo& event) { | 656 const MouseEventWithLatencyInfo& event) { |
601 const WebMouseEvent& mouse_event = event.event; | 657 const WebMouseEvent& mouse_event = event.event; |
602 int x = mouse_event.x, y = mouse_event.y; | 658 int x = mouse_event.x, y = mouse_event.y; |
603 float dx = mouse_event.movementX, dy = mouse_event.movementY; | 659 float dx = mouse_event.movementX, dy = mouse_event.movementY; |
604 static int startX = 0, startY = 0; | 660 static int startX = 0, startY = 0; |
605 | 661 |
606 switch (mouse_event.button) { | 662 switch (mouse_event.button) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 break; | 731 break; |
676 } | 732 } |
677 } | 733 } |
678 | 734 |
679 bool ImmediateInputRouter::IsInOverscrollGesture() const { | 735 bool ImmediateInputRouter::IsInOverscrollGesture() const { |
680 OverscrollController* controller = client_->GetOverscrollController(); | 736 OverscrollController* controller = client_->GetOverscrollController(); |
681 return controller && controller->overscroll_mode() != OVERSCROLL_NONE; | 737 return controller && controller->overscroll_mode() != OVERSCROLL_NONE; |
682 } | 738 } |
683 | 739 |
684 } // namespace content | 740 } // namespace content |
OLD | NEW |