Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(84)

Side by Side Diff: content/browser/renderer_host/input/immediate_input_router.cc

Issue 67383002: Initial browser-side implementation for touch-action (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698