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

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: More 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/logging.h"
9 #include "content/common/input/web_input_event_traits.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 InputEventAckState TransitionToMostRestrictiveState(
tdresser 2014/01/16 14:31:45 TransitionToMostRestrictiveState implies that this
jdduke (slow) 2014/01/16 17:17:53 Yeah, except the order matters (i.e., we never go
20 InputEventAckState ack_old,
21 InputEventAckState ack_new) {
22 if (ack_new == INPUT_EVENT_ACK_STATE_UNKNOWN) {
23 NOTREACHED() << "New acks should never be undefined.";
24 return ack_old;
25 }
26
27 if (ack_old == INPUT_EVENT_ACK_STATE_UNKNOWN ||
28 ack_old == INPUT_EVENT_ACK_STATE_NOT_CONSUMED)
29 return ack_new;
30
31 // If a partial touch sequence has been consumed, or has no consumer,
32 // subsequent touches have no bearing on the overall gesture disposition.
33 return ack_old;
34 }
35
36 WebGestureEvent CreateGesture(WebInputEvent::Type type) {
37 DCHECK(WebInputEvent::isGestureEventType(type));
38 WebGestureEvent event;
39 event.type = type;
40 event.sourceDevice = WebGestureEvent::Touchscreen;
41 return event;
42 }
43
44 } // namespace
45
46 GestureEventQueue::GestureEventQueue(GestureEventQueueClient* client)
47 : client_(client),
48 outstanding_tap_(false),
49 outstanding_fling_(false) {
50 DCHECK(client_);
51 }
52
53 GestureEventQueue::~GestureEventQueue() {}
54
55 void GestureEventQueue::OnGestureEventPacket(const GestureEventPacket& packet) {
56 switch (packet.gesture_source()) {
57 case GestureEventPacket::TOUCH_BEGIN:
58 sequences_.push_back(GestureSequence());
59 break;
60 case GestureEventPacket::TOUCH:
61 break;
62 case GestureEventPacket::TOUCH_TIMEOUT:
63 // Touches preceding the timeout event are still awaiting an ack.
64 if (!Tail().IsEmpty())
65 break;
66 // Touches preceding the timeout were handled and gestures are allowed.
67 if (Tail().IsGestureAllowed())
68 Forward(packet);
69 // The timeout gesture should be dropped.
70 return;
71 case GestureEventPacket::SYNTHETIC:
tdresser 2014/01/16 14:31:45 Couldn't this violate some ordering constraints?
jdduke (slow) 2014/01/16 17:17:53 Yeah, though on Android that constraint is already
tdresser 2014/01/16 18:28:29 SGTM.
72 Forward(packet);
73 return;
74 }
75
76 Tail().Push(packet);
77 }
78
79 void GestureEventQueue::OnTouchEventAck(InputEventAckState ack_state) {
80 // Transition to the next touch sequence. This transition is deferred
81 // until the ack in the event that the sequence receives a timeout event.
tdresser 2014/01/16 14:31:45 This is the only place where you're transitioning
jdduke (slow) 2014/01/16 17:17:53 It's a terrible comment. I was thinking of adding
82 if (Head().IsEmpty()) {
83 CancelTapIfNecessary();
84 CancelFlingIfNecessary();
85 sequences_.pop_front();
86 }
87
88 Forward(Head().OnTouchEventAck(ack_state));
89
90 // Immediately cancel a TapDown if TouchStart went unconsumed, but a
91 // subsequent TouchMove is consumed.
92 if (!Head().IsGestureAllowed())
93 CancelTapIfNecessary();
94 }
95
96 void GestureEventQueue::Forward(const GestureEventPacket& packet) {
97 for (size_t i = 0; i < packet.gesture_count(); ++i)
98 Forward(packet.gesture(i));
99 }
100
101 void GestureEventQueue::Forward(const WebGestureEvent& event) {
102 switch (event.type) {
103 case WebInputEvent::GestureScrollBegin:
104 CancelTapIfNecessary();
105 break;
106 case WebInputEvent::GestureTapDown:
107 outstanding_tap_ = true;
108 break;
109 case WebInputEvent::GestureTapCancel:
110 case WebInputEvent::GestureTap:
111 case WebInputEvent::GestureTapUnconfirmed:
112 case WebInputEvent::GestureDoubleTap:
113 outstanding_tap_ = false;
114 break;
115 case WebInputEvent::GestureFlingStart:
116 outstanding_fling_ = true;
117 break;
118 case WebInputEvent::GestureFlingCancel:
119 outstanding_fling_ = false;
120 break;
121 default:
122 break;
123 }
124 client_->ForwardGestureEvent(event);
125 }
126
127 void GestureEventQueue::CancelTapIfNecessary() {
128 if (!outstanding_tap_)
129 return;
130
131 Forward(CreateGesture(WebInputEvent::GestureTapCancel));
132 DCHECK(!outstanding_tap_);
133 }
134
135 void GestureEventQueue::CancelFlingIfNecessary() {
136 if (!outstanding_fling_)
137 return;
138
139 Forward(CreateGesture(WebInputEvent::GestureFlingCancel));
140 DCHECK(!outstanding_fling_);
141 }
142
143 GestureEventQueue::GestureSequence& GestureEventQueue::Head() {
144 DCHECK(!sequences_.empty());
145 return sequences_.front();
146 }
147
148 GestureEventQueue::GestureSequence& GestureEventQueue::Tail() {
149 DCHECK(!sequences_.empty());
150 return sequences_.back();
151 }
152
153
154 GestureEventQueue::GestureSequence::GestureSequence()
155 : ack_state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {}
156
157 GestureEventQueue::GestureSequence::~GestureSequence() {}
158
159 void GestureEventQueue::GestureSequence::Push(
160 const GestureEventPacket& packet) {
161 DCHECK_NE(GestureEventPacket::SYNTHETIC, packet.gesture_source());
162 if (packet.gesture_source() == GestureEventPacket::TOUCH_TIMEOUT) {
163 // Timeout-derived gestures should have beeen forwarded or dropped
tdresser 2014/01/16 14:31:45 beeen -> been
jdduke (slow) 2014/01/16 17:17:53 Done.
164 // immediately if the sequence was empty.
165 DCHECK(!IsEmpty());
166
167 // Merge the timeout packet with the previous packet, simplifying dispatch
168 // when the touch ack preceding the timeout is received.
169 for (size_t i = 0; i < packet.gesture_count(); ++i)
170 sequence_.back().Push(packet.gesture(i));
171 return;
172 }
173 sequence_.push_back(packet);
174 }
175
176 GestureEventPacket GestureEventQueue::GestureSequence::OnTouchEventAck(
177 InputEventAckState new_ack_state) {
178 DCHECK(!IsEmpty());
179
180 ack_state_ = TransitionToMostRestrictiveState(ack_state_, new_ack_state);
181 DCHECK_NE(ack_state_, INPUT_EVENT_ACK_STATE_UNKNOWN);
182
183 GestureEventPacket gestures =
184 IsGestureAllowed() ? sequence_.front() : GestureEventPacket();
185 sequence_.pop_front();
186 return gestures;
187 }
188
189 bool GestureEventQueue::GestureSequence::IsGestureAllowed() const {
190 return ack_state_ == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS ||
191 ack_state_ == INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
192 }
193
194 bool GestureEventQueue::GestureSequence::IsEmpty() const {
195 return sequence_.empty();
196 }
197
198 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698