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

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: Findbugs fix 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 #include "content/common/input/web_input_event_traits.h"
11
12 using blink::WebGestureEvent;
13 using blink::WebInputEvent;
14 using blink::WebTouchEvent;
15 using blink::WebTouchPoint;
16
17 namespace content {
18 namespace {
19
20 WebGestureEvent CreateGesture(WebInputEvent::Type type) {
21 DCHECK(WebInputEvent::isGestureEventType(type));
22 WebGestureEvent event;
23 event.type = type;
24 event.sourceDevice = WebGestureEvent::Touchscreen;
25 return event;
26 }
27
28 } // namespace
29
30 GestureEventQueue::GestureEventQueue(GestureEventQueueClient* client)
31 : client_(client),
32 packet_sender_(base::Bind(&GestureEventQueue::SendPacket,
33 base::Unretained(this))),
34 outstanding_tap_(false),
35 outstanding_fling_(false) {
36 DCHECK(client_);
37 }
38
39 GestureEventQueue::~GestureEventQueue() {}
40
41 void GestureEventQueue::OnGestureEventPacket(const GestureEventPacket& packet) {
42 switch (packet.gesture_source()) {
43 case GestureEventPacket::TOUCH_BEGIN:
44 sequences_.push_back(GestureSequence());
45 break;
46
47 case GestureEventPacket::TOUCH:
48 break;
49
50 case GestureEventPacket::TOUCH_TIMEOUT:
Rick Byers 2014/01/21 20:10:10 This special handling for TOUCH_TIMEOUT and SYNTHE
jdduke (slow) 2014/01/21 20:52:38 It's not redundant, unfortunately. Synthetic pac
Rick Byers 2014/01/23 20:45:29 Sorry, what I meant was that we've got two separat
51 // Handle the timeout packet immediately if the packet preceding the
52 // timeout has already been dispatched.
53 if (Tail().IsEmpty()) {
54 if (Tail().IsGestureAllowed())
55 SendPacket(packet);
56 return;
57 }
58 break;
59
60 case GestureEventPacket::SYNTHETIC:
61 // Handle the synthetic packet immediately if no other packets pending.
Rick Byers 2014/01/21 20:10:10 Can you talk a bit about why synthetic gestures ar
jdduke (slow) 2014/01/21 20:52:38 This is done for things like WebView's zoom contro
Rick Byers 2014/01/23 20:45:29 Ah, thanks! I had forgotten we used synthetic ges
62 if (sequences_.empty() || Tail().IsEmpty()) {
63 SendPacket(packet);
64 return;
65 }
66 // Otherwise, queue the packet and process it in-order, irrespective
67 // of the touch sequence disposition.
68 break;
69 }
70
71 Tail().Push(packet);
72 }
73
74 void GestureEventQueue::OnTouchEventAck(InputEventAckState ack_state) {
75 if (Head().IsEmpty()) {
76 CancelTapIfNecessary();
77 CancelFlingIfNecessary();
78 sequences_.pop_front();
79 }
80
81 Head().OnTouchEventAck(ack_state, packet_sender_);
82
83 // Immediately cancel a TapDown if TouchStart went unconsumed, but a
84 // subsequent TouchMove is consumed.
85 if (!Head().IsGestureAllowed())
86 CancelTapIfNecessary();
87 }
88
89 InputEventAckState GestureEventQueue::GetMostRestrictiveState(
90 InputEventAckState ack_old,
91 InputEventAckState ack_new) {
92 switch (ack_old) {
93 case INPUT_EVENT_ACK_STATE_UNKNOWN:
94 return ack_new;
95
96 case INPUT_EVENT_ACK_STATE_NOT_CONSUMED:
97 return ack_new == INPUT_EVENT_ACK_STATE_CONSUMED ? ack_new : ack_old;
98
99 case INPUT_EVENT_ACK_STATE_CONSUMED:
100 case INPUT_EVENT_ACK_STATE_IGNORED:
101 case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS:
102 default:
103 return ack_old;
104 };
105 }
106
107 void GestureEventQueue::SendPacket(const GestureEventPacket& packet) {
108 for (size_t i = 0; i < packet.gesture_count(); ++i)
109 SendGesture(packet.gesture(i));
110 }
111
112 void GestureEventQueue::SendGesture(const WebGestureEvent& event) {
113 switch (event.type) {
114 case WebInputEvent::GestureScrollBegin:
115 case WebInputEvent::GestureLongTap:
116 CancelTapIfNecessary();
117 break;
118 case WebInputEvent::GestureTapDown:
119 outstanding_tap_ = true;
120 break;
121 case WebInputEvent::GestureTapCancel:
122 case WebInputEvent::GestureTap:
123 case WebInputEvent::GestureTapUnconfirmed:
124 case WebInputEvent::GestureDoubleTap:
125 outstanding_tap_ = false;
126 break;
127 case WebInputEvent::GestureFlingStart:
128 CancelFlingIfNecessary();
129 outstanding_fling_ = true;
130 break;
131 case WebInputEvent::GestureFlingCancel:
132 outstanding_fling_ = false;
133 break;
134 default:
135 break;
136 }
137 client_->ForwardGestureEvent(event);
138 }
139
140 void GestureEventQueue::CancelTapIfNecessary() {
141 if (!outstanding_tap_)
142 return;
143
144 SendGesture(CreateGesture(WebInputEvent::GestureTapCancel));
145 DCHECK(!outstanding_tap_);
146 }
147
148 void GestureEventQueue::CancelFlingIfNecessary() {
149 if (!outstanding_fling_)
150 return;
151
152 SendGesture(CreateGesture(WebInputEvent::GestureFlingCancel));
153 DCHECK(!outstanding_fling_);
154 }
155
156 GestureEventQueue::GestureSequence& GestureEventQueue::Head() {
157 DCHECK(!sequences_.empty());
158 return sequences_.front();
159 }
160
161 GestureEventQueue::GestureSequence& GestureEventQueue::Tail() {
162 DCHECK(!sequences_.empty());
163 return sequences_.back();
164 }
165
166
167 GestureEventQueue::GestureSequence::GestureSequence()
168 : ack_state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {}
169
170 GestureEventQueue::GestureSequence::~GestureSequence() {}
171
172 void GestureEventQueue::GestureSequence::Push(
173 const GestureEventPacket& packet) {
174 if (packet.gesture_source() == GestureEventPacket::TOUCH_TIMEOUT ||
175 packet.gesture_source() == GestureEventPacket::SYNTHETIC) {
176 // Timeout-derived gestures should have been forwarded or dropped
177 // immediately if the sequence was empty.
178 DCHECK(!IsEmpty());
179 }
180 sequence_.push_back(packet);
181 }
182
183 void GestureEventQueue::GestureSequence::OnTouchEventAck(
184 InputEventAckState new_ack_state,
185 const PacketSender& packet_sender) {
186 DCHECK_NE(INPUT_EVENT_ACK_STATE_UNKNOWN, new_ack_state);
187
188 InputEventAckState old_ack_state = ack_state_;
189 ack_state_ = GetMostRestrictiveState(old_ack_state, new_ack_state);
Rick Byers 2014/01/21 20:10:10 Couldn't this just be a single bit "is gesture all
jdduke (slow) 2014/01/21 20:52:38 It is awkward, and I'm not opposed to using a uniq
Rick Byers 2014/01/23 20:45:29 Cool, I like this better (has a nice symmetry with
190
191 bool packet_for_current_ack_handled = false;
192 while (!IsEmpty()) {
193 const GestureEventPacket& packet = sequence_.front();
194
195 switch (packet.gesture_source()) {
196 case GestureEventPacket::TOUCH_BEGIN:
197 case GestureEventPacket::TOUCH:
198 // We should handle at most one packet corresponding to a given ack.
199 if (packet_for_current_ack_handled)
200 return;
201 packet_for_current_ack_handled = true;
202
203 if (IsGestureAllowed())
204 packet_sender.Run(packet);
205 break;
206
207 case GestureEventPacket::TOUCH_TIMEOUT:
208 if (IsGestureAllowed())
209 packet_sender.Run(packet);
210 break;
211
212 case GestureEventPacket::SYNTHETIC:
213 // Synthetic gestures should be dispatched regardless of the touch
214 // sequence disposition.
215 packet_sender.Run(packet);
216 break;
217 };
218
219 sequence_.pop_front();
220 }
221 DCHECK(packet_for_current_ack_handled);
222 }
223
224 bool GestureEventQueue::GestureSequence::IsGestureAllowed() const {
225 return ack_state_ == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS ||
226 ack_state_ == INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
227 }
228
229 bool GestureEventQueue::GestureSequence::IsEmpty() const {
230 return sequence_.empty();
231 }
232
233 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698