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

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

Issue 120513005: [Android] Perform eager gesture recognition on MotionEvents (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Allow scrolling after longpress Created 6 years, 11 months 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/browser/renderer_host/input/gesture_event_queue.h"
6
7 #include "base/auto_reset.h"
8 #include "base/bind.h"
9 #include "base/logging.h"
10
11 using blink::WebGestureEvent;
12 using blink::WebInputEvent;
13 using blink::WebTouchEvent;
14 using blink::WebTouchPoint;
15
16 namespace content {
17 namespace {
18
19 WebGestureEvent CreateGesture(WebInputEvent::Type type) {
20 DCHECK(WebInputEvent::isGestureEventType(type));
21 WebGestureEvent event;
22 event.type = type;
23 event.sourceDevice = WebGestureEvent::Touchscreen;
24 return event;
25 }
26
27 } // namespace
28
29 // GestureEventQueue
30
31 GestureEventQueue::GestureEventQueue(GestureEventQueueClient* client)
32 : client_(client),
33 packet_sender_(base::Bind(&GestureEventQueue::SendPacket,
34 base::Unretained(this))),
35 needs_tap_ending_event_(false),
36 needs_fling_ending_event_(false) {
37 DCHECK(client_);
38 }
39
40 GestureEventQueue::~GestureEventQueue() {}
41
42 void GestureEventQueue::OnGestureEventPacket(const GestureEventPacket& packet) {
43 switch (packet.gesture_source()) {
44 case GestureEventPacket::TOUCH_BEGIN:
45 sequences_.push(GestureSequence());
46 break;
47
48 case GestureEventPacket::TOUCH:
49 break;
50
51 case GestureEventPacket::TOUCH_TIMEOUT:
52 // Handle the timeout packet immediately if the packet preceding the
53 // timeout has already been dispatched.
54 if (Tail().IsEmpty()) {
55 if (!Tail().IsGesturePrevented())
56 SendPacket(packet);
57 return;
58 }
59 break;
60
61 case GestureEventPacket::INVALID:
62 NOTREACHED() << "Invalid gesture packet detected.";
63 break;
64 }
65
66 Tail().Push(packet);
67 }
68
69 void GestureEventQueue::OnTouchEventAck(InputEventAckState ack_state) {
70 DCHECK(!sequences_.empty());
71 if (Head().IsEmpty()) {
72 CancelTapIfNecessary();
73 CancelFlingIfNecessary();
74 sequences_.pop();
75 }
76
77 DCHECK(!sequences_.empty());
78 Head().OnTouchEventAck(ack_state, packet_sender_);
79
80 // Immediately cancel a TapDown if TouchStart went unconsumed, but a
81 // subsequent TouchMove is consumed.
82 if (Head().IsGesturePrevented())
83 CancelTapIfNecessary();
84 }
85
86 void GestureEventQueue::SendPacket(const GestureEventPacket& packet) {
87 for (size_t i = 0; i < packet.gesture_count(); ++i)
88 SendGesture(packet.gesture(i));
89 }
90
91 void GestureEventQueue::SendGesture(const WebGestureEvent& event) {
92 switch (event.type) {
93 case WebInputEvent::GestureLongTap:
94 CancelTapIfNecessary();
95 CancelFlingIfNecessary();
96 break;
97 case WebInputEvent::GestureTapDown:
98 needs_tap_ending_event_ = true;
99 break;
100 case WebInputEvent::GestureTapCancel:
101 case WebInputEvent::GestureTap:
102 case WebInputEvent::GestureTapUnconfirmed:
103 case WebInputEvent::GestureDoubleTap:
104 needs_tap_ending_event_ = false;
105 break;
106 case WebInputEvent::GestureScrollBegin:
107 CancelTapIfNecessary();
108 CancelFlingIfNecessary();
109 break;
110 case WebInputEvent::GestureFlingStart:
111 CancelFlingIfNecessary();
112 needs_fling_ending_event_ = true;
113 break;
114 case WebInputEvent::GestureFlingCancel:
115 needs_fling_ending_event_ = false;
116 break;
117 default:
118 break;
119 }
120 client_->ForwardGestureEvent(event);
121 }
122
123 void GestureEventQueue::CancelTapIfNecessary() {
124 if (!needs_tap_ending_event_)
125 return;
126
127 SendGesture(CreateGesture(WebInputEvent::GestureTapCancel));
128 DCHECK(!needs_tap_ending_event_);
129 }
130
131 void GestureEventQueue::CancelFlingIfNecessary() {
132 if (!needs_fling_ending_event_)
133 return;
134
135 SendGesture(CreateGesture(WebInputEvent::GestureFlingCancel));
136 DCHECK(!needs_fling_ending_event_);
137 }
138
139 GestureEventQueue::GestureSequence& GestureEventQueue::Head() {
140 DCHECK(!sequences_.empty());
141 return sequences_.front();
142 }
143
144 GestureEventQueue::GestureSequence& GestureEventQueue::Tail() {
145 DCHECK(!sequences_.empty());
146 return sequences_.back();
147 }
148
149
150 // GestureEventQueue::GestureSequence
151
152 GestureEventQueue::GestureSequence::GestureSequence()
153 : state_(PENDING) {}
154
155 GestureEventQueue::GestureSequence::~GestureSequence() {}
156
157 void GestureEventQueue::GestureSequence::Push(
158 const GestureEventPacket& packet) {
159 // Timeout-derived gestures should have been forwarded or dropped
160 // immediately if the sequence was empty.
161 DCHECK(packet.gesture_source() != GestureEventPacket::TOUCH_TIMEOUT ||
162 !IsEmpty());
163 sequence_.push(packet);
164 }
165
166 void GestureEventQueue::GestureSequence::OnTouchEventAck(
167 InputEventAckState ack_state,
168 const PacketSender& packet_sender) {
169 DCHECK_NE(INPUT_EVENT_ACK_STATE_UNKNOWN, ack_state);
170
171 if (state_ == PENDING || state_ == ALLOWED_UNTIL_PREVENTED) {
172 // |NO_CONSUMER| should only be effective when the *first* touch is ack'ed.
173 if (state_ == PENDING &&
174 ack_state == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS)
175 state_ = ALWAYS_ALLOWED;
176 else if (ack_state == INPUT_EVENT_ACK_STATE_CONSUMED)
177 state_ = ALWAYS_PREVENTED;
178 else
179 state_ = ALLOWED_UNTIL_PREVENTED;
180 }
181
182 bool packet_for_current_ack_handled = false;
183 while (!IsEmpty()) {
184 const GestureEventPacket& packet = sequence_.front();
185
186 switch (packet.gesture_source()) {
187 case GestureEventPacket::TOUCH_BEGIN:
188 case GestureEventPacket::TOUCH:
189 // We should handle at most one packet corresponding to a given ack.
190 if (packet_for_current_ack_handled)
191 return;
192 packet_for_current_ack_handled = true;
193
194 if (!IsGesturePrevented())
195 packet_sender.Run(packet);
196 break;
197
198 case GestureEventPacket::TOUCH_TIMEOUT:
199 if (!IsGesturePrevented())
200 packet_sender.Run(packet);
201 break;
202
203 case GestureEventPacket::INVALID:
204 NOTREACHED() << "Invalid gesture packet in sequence.";
205 };
206
207 sequence_.pop();
208 }
209 DCHECK(packet_for_current_ack_handled);
210 }
211
212 bool GestureEventQueue::GestureSequence::IsGesturePrevented() const {
213 return state_ == ALWAYS_PREVENTED;
214 }
215
216 bool GestureEventQueue::GestureSequence::IsEmpty() const {
217 return sequence_.empty();
218 }
219
220 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698