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

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: Code review and test cleanup 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::SYNTHETIC:
62 // Handle the synthetic packet immediately if no other packets pending.
63 if (sequences_.empty() || Tail().IsEmpty()) {
64 SendPacket(packet);
65 return;
66 }
67 // Otherwise, queue the packet and process it in-order, irrespective
68 // of the touch sequence disposition.
69 break;
70 }
71
72 Tail().Push(packet);
73 }
74
75 void GestureEventQueue::OnTouchEventAck(InputEventAckState ack_state) {
76 DCHECK(!sequences_.empty());
77 if (Head().IsEmpty()) {
78 CancelTapIfNecessary();
79 CancelFlingIfNecessary();
80 sequences_.pop();
81 }
82
83 DCHECK(!sequences_.empty());
84 Head().OnTouchEventAck(ack_state, packet_sender_);
85
86 // Immediately cancel a TapDown if TouchStart went unconsumed, but a
87 // subsequent TouchMove is consumed.
88 if (Head().IsGesturePrevented())
89 CancelTapIfNecessary();
90 }
91
92 void GestureEventQueue::SendPacket(const GestureEventPacket& packet) {
93 for (size_t i = 0; i < packet.gesture_count(); ++i)
94 SendGesture(packet.gesture(i));
95 }
96
97 void GestureEventQueue::SendGesture(const WebGestureEvent& event) {
98 switch (event.type) {
99 case WebInputEvent::GestureLongTap:
100 CancelTapIfNecessary();
101 CancelFlingIfNecessary();
102 break;
103 case WebInputEvent::GestureTapDown:
104 needs_tap_ending_event_ = true;
105 break;
106 case WebInputEvent::GestureTapCancel:
107 case WebInputEvent::GestureTap:
108 case WebInputEvent::GestureTapUnconfirmed:
109 case WebInputEvent::GestureDoubleTap:
110 needs_tap_ending_event_ = false;
111 break;
112 case WebInputEvent::GestureScrollBegin:
113 CancelTapIfNecessary();
114 CancelFlingIfNecessary();
115 break;
116 case WebInputEvent::GestureFlingStart:
117 CancelFlingIfNecessary();
118 needs_fling_ending_event_ = true;
119 break;
120 case WebInputEvent::GestureFlingCancel:
121 needs_fling_ending_event_ = false;
122 break;
123 default:
124 break;
125 }
126 client_->ForwardGestureEvent(event);
127 }
128
129 void GestureEventQueue::CancelTapIfNecessary() {
130 if (!needs_tap_ending_event_)
131 return;
132
133 SendGesture(CreateGesture(WebInputEvent::GestureTapCancel));
134 DCHECK(!needs_tap_ending_event_);
135 }
136
137 void GestureEventQueue::CancelFlingIfNecessary() {
138 if (!needs_fling_ending_event_)
139 return;
140
141 SendGesture(CreateGesture(WebInputEvent::GestureFlingCancel));
142 DCHECK(!needs_fling_ending_event_);
143 }
144
145 GestureEventQueue::GestureSequence& GestureEventQueue::Head() {
146 DCHECK(!sequences_.empty());
147 return sequences_.front();
148 }
149
150 GestureEventQueue::GestureSequence& GestureEventQueue::Tail() {
151 DCHECK(!sequences_.empty());
152 return sequences_.back();
153 }
154
155
156 // GestureEventQueue::GestureSequence
157
158 GestureEventQueue::GestureSequence::GestureSequence()
159 : state_(PENDING) {}
160
161 GestureEventQueue::GestureSequence::~GestureSequence() {}
162
163 void GestureEventQueue::GestureSequence::Push(
164 const GestureEventPacket& packet) {
165 if (packet.gesture_source() == GestureEventPacket::TOUCH_TIMEOUT ||
166 packet.gesture_source() == GestureEventPacket::SYNTHETIC) {
167 // Timeout-derived gestures should have been forwarded or dropped
168 // immediately if the sequence was empty.
169 DCHECK(!IsEmpty());
170 }
171 sequence_.push(packet);
172 }
173
174 void GestureEventQueue::GestureSequence::OnTouchEventAck(
175 InputEventAckState ack_state,
176 const PacketSender& packet_sender) {
177 DCHECK_NE(INPUT_EVENT_ACK_STATE_UNKNOWN, ack_state);
178
179 if (state_ == PENDING || state_ == ALLOWED_UNTIL_PREVENTED) {
180 // |NO_CONSUMER| should only be effective when the *first* touch is ack'ed.
181 if (state_ == PENDING &&
182 ack_state == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS)
183 state_ = ALWAYS_ALLOWED;
184 else if (ack_state == INPUT_EVENT_ACK_STATE_CONSUMED)
185 state_ = ALWAYS_PREVENTED;
186 else
187 state_ = ALLOWED_UNTIL_PREVENTED;
188 }
189
190 bool packet_for_current_ack_handled = false;
191 while (!IsEmpty()) {
192 const GestureEventPacket& packet = sequence_.front();
193
194 switch (packet.gesture_source()) {
195 case GestureEventPacket::TOUCH_BEGIN:
196 case GestureEventPacket::TOUCH:
197 // We should handle at most one packet corresponding to a given ack.
198 if (packet_for_current_ack_handled)
199 return;
200 packet_for_current_ack_handled = true;
201
202 if (!IsGesturePrevented())
203 packet_sender.Run(packet);
204 break;
205
206 case GestureEventPacket::TOUCH_TIMEOUT:
207 if (!IsGesturePrevented())
208 packet_sender.Run(packet);
209 break;
210
211 case GestureEventPacket::SYNTHETIC:
212 // Synthetic gestures should be dispatched regardless of the touch
213 // sequence disposition.
214 packet_sender.Run(packet);
215 break;
216 };
217
218 sequence_.pop();
219 }
220 DCHECK(packet_for_current_ack_handled);
221 }
222
223 bool GestureEventQueue::GestureSequence::IsGesturePrevented() const {
224 return state_ == ALWAYS_PREVENTED;
225 }
226
227 bool GestureEventQueue::GestureSequence::IsEmpty() const {
228 return sequence_.empty();
229 }
230
231 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698