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

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

Powered by Google App Engine
This is Rietveld 408576698