touch_disposition_gesture_filter.cc 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. // Copyright 2014 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. #include "ui/events/gesture_detection/touch_disposition_gesture_filter.h"
  5. #include <stddef.h>
  6. #include "base/auto_reset.h"
  7. #include "base/check_op.h"
  8. #include "base/notreached.h"
  9. #include "ui/events/gesture_event_details.h"
  10. namespace ui {
  11. namespace {
  12. // A BitSet32 is used for tracking dropped gesture types.
  13. static_assert(ET_GESTURE_TYPE_END - ET_GESTURE_TYPE_START < 32,
  14. "gesture type count too large");
  15. GestureEventData CreateGesture(EventType type,
  16. int motion_event_id,
  17. MotionEvent::ToolType primary_tool_type,
  18. const GestureEventDataPacket& packet) {
  19. // As the event is purely synthetic, we needn't be strict with event flags.
  20. int flags = EF_NONE;
  21. GestureEventDetails details(type);
  22. details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
  23. return GestureEventData(details,
  24. motion_event_id,
  25. primary_tool_type,
  26. packet.timestamp(),
  27. packet.touch_location().x(),
  28. packet.touch_location().y(),
  29. packet.raw_touch_location().x(),
  30. packet.raw_touch_location().y(),
  31. 1,
  32. gfx::RectF(packet.touch_location(), gfx::SizeF()),
  33. flags,
  34. packet.unique_touch_event_id());
  35. }
  36. enum RequiredTouches {
  37. RT_NONE = 0,
  38. RT_START = 1 << 0,
  39. RT_CURRENT = 1 << 1,
  40. };
  41. struct DispositionHandlingInfo {
  42. // A bitwise-OR of |RequiredTouches|.
  43. int required_touches;
  44. EventType antecedent_event_type;
  45. explicit DispositionHandlingInfo(int required_touches)
  46. : required_touches(required_touches), antecedent_event_type(ET_UNKNOWN) {}
  47. DispositionHandlingInfo(int required_touches,
  48. EventType antecedent_event_type)
  49. : required_touches(required_touches),
  50. antecedent_event_type(antecedent_event_type) {}
  51. };
  52. DispositionHandlingInfo Info(int required_touches) {
  53. return DispositionHandlingInfo(required_touches);
  54. }
  55. DispositionHandlingInfo Info(int required_touches,
  56. EventType antecedent_event_type) {
  57. return DispositionHandlingInfo(required_touches, antecedent_event_type);
  58. }
  59. // This approach to disposition handling is described at http://goo.gl/5G8PWJ.
  60. DispositionHandlingInfo GetDispositionHandlingInfo(EventType type) {
  61. switch (type) {
  62. case ET_GESTURE_TAP_DOWN:
  63. return Info(RT_START);
  64. case ET_GESTURE_TAP_CANCEL:
  65. return Info(RT_START);
  66. case ET_GESTURE_SHOW_PRESS:
  67. return Info(RT_START);
  68. case ET_GESTURE_LONG_PRESS:
  69. return Info(RT_START);
  70. case ET_GESTURE_SHORT_PRESS:
  71. return Info(RT_START);
  72. case ET_GESTURE_LONG_TAP:
  73. return Info(RT_START | RT_CURRENT);
  74. case ET_GESTURE_TAP:
  75. return Info(RT_START | RT_CURRENT, ET_GESTURE_TAP_UNCONFIRMED);
  76. case ET_GESTURE_TAP_UNCONFIRMED:
  77. return Info(RT_START | RT_CURRENT);
  78. case ET_GESTURE_DOUBLE_TAP:
  79. return Info(RT_START | RT_CURRENT, ET_GESTURE_TAP_UNCONFIRMED);
  80. case ET_GESTURE_SCROLL_BEGIN:
  81. return Info(RT_START);
  82. case ET_GESTURE_SCROLL_UPDATE:
  83. return Info(RT_CURRENT, ET_GESTURE_SCROLL_BEGIN);
  84. case ET_GESTURE_SCROLL_END:
  85. return Info(RT_NONE, ET_GESTURE_SCROLL_BEGIN);
  86. case ET_SCROLL_FLING_START:
  87. // We rely on |EndScrollGestureIfNecessary| to end the scroll if the fling
  88. // start is prevented.
  89. return Info(RT_NONE, ET_GESTURE_SCROLL_UPDATE);
  90. case ET_SCROLL_FLING_CANCEL:
  91. return Info(RT_NONE, ET_SCROLL_FLING_START);
  92. case ET_GESTURE_PINCH_BEGIN:
  93. return Info(RT_START, ET_GESTURE_SCROLL_BEGIN);
  94. case ET_GESTURE_PINCH_UPDATE:
  95. return Info(RT_CURRENT, ET_GESTURE_PINCH_BEGIN);
  96. case ET_GESTURE_PINCH_END:
  97. return Info(RT_NONE, ET_GESTURE_PINCH_BEGIN);
  98. case ET_GESTURE_BEGIN:
  99. return Info(RT_START);
  100. case ET_GESTURE_END:
  101. return Info(RT_NONE, ET_GESTURE_BEGIN);
  102. case ET_GESTURE_SWIPE:
  103. return Info(RT_START, ET_GESTURE_SCROLL_BEGIN);
  104. case ET_GESTURE_TWO_FINGER_TAP:
  105. return Info(RT_START);
  106. default:
  107. break;
  108. }
  109. NOTREACHED();
  110. return Info(RT_NONE);
  111. }
  112. int GetGestureTypeIndex(EventType type) {
  113. DCHECK_GE(type, ET_GESTURE_TYPE_START);
  114. DCHECK_LE(type, ET_GESTURE_TYPE_END);
  115. return type - ET_GESTURE_TYPE_START;
  116. }
  117. bool IsTouchStartEvent(GestureEventDataPacket::GestureSource gesture_source) {
  118. return gesture_source == GestureEventDataPacket::TOUCH_SEQUENCE_START ||
  119. gesture_source == GestureEventDataPacket::TOUCH_START;
  120. }
  121. } // namespace
  122. // TouchDispositionGestureFilter
  123. TouchDispositionGestureFilter::TouchDispositionGestureFilter(
  124. TouchDispositionGestureFilterClient* client)
  125. : client_(client),
  126. ending_event_motion_event_id_(0),
  127. ending_event_primary_tool_type_(MotionEvent::ToolType::UNKNOWN),
  128. needs_tap_ending_event_(false),
  129. needs_show_press_event_(false),
  130. needs_fling_ending_event_(false),
  131. needs_scroll_ending_event_(false) {
  132. DCHECK(client_);
  133. }
  134. TouchDispositionGestureFilter::~TouchDispositionGestureFilter() {
  135. }
  136. TouchDispositionGestureFilter::PacketResult
  137. TouchDispositionGestureFilter::OnGesturePacket(
  138. const GestureEventDataPacket& packet) {
  139. if (packet.gesture_source() == GestureEventDataPacket::UNDEFINED ||
  140. packet.gesture_source() == GestureEventDataPacket::INVALID)
  141. return INVALID_PACKET_TYPE;
  142. if (packet.gesture_source() == GestureEventDataPacket::TOUCH_SEQUENCE_START)
  143. sequences_.push(GestureSequence());
  144. if (IsEmpty())
  145. return INVALID_PACKET_ORDER;
  146. if (packet.gesture_source() == GestureEventDataPacket::TOUCH_TIMEOUT &&
  147. Tail().empty()) {
  148. // Handle the timeout packet immediately if the packet preceding the timeout
  149. // has already been dispatched.
  150. FilterAndSendPacket(packet);
  151. return SUCCESS;
  152. }
  153. // Check the packet's unique_touch_event_id is valid and unique with the
  154. // exception of TOUCH_TIMEOUT packets which may share an id with other events.
  155. // |TOUCH_TIMEOUT| packets don't wait for an ack, they are dispatched
  156. // as soon as they reach the head of the queue, in |SendAckedEvents|.
  157. if (!Tail().empty()) {
  158. DCHECK((packet.gesture_source() == GestureEventDataPacket::TOUCH_TIMEOUT)
  159. || (packet.unique_touch_event_id() !=
  160. Tail().back().unique_touch_event_id()));
  161. }
  162. if (!Head().empty()) {
  163. DCHECK((packet.gesture_source() == GestureEventDataPacket::TOUCH_TIMEOUT) ||
  164. packet.unique_touch_event_id() !=
  165. Head().front().unique_touch_event_id());
  166. }
  167. Tail().push(packet);
  168. return SUCCESS;
  169. }
  170. void TouchDispositionGestureFilter::OnTouchEventAck(
  171. uint32_t unique_touch_event_id,
  172. bool event_consumed,
  173. bool is_source_touch_event_set_blocking) {
  174. // Spurious asynchronous acks should not trigger a crash.
  175. if (IsEmpty() || (Head().empty() && sequences_.size() == 1))
  176. return;
  177. if (Head().empty())
  178. PopGestureSequence();
  179. // If the tail's event_source is TOUCH_TIMEOUT, then it may share a
  180. // unique_touch_event_id() with another event; in this case don't ack it here.
  181. if (!Tail().empty() &&
  182. Tail().back().unique_touch_event_id() == unique_touch_event_id &&
  183. Tail().back().gesture_source() != GestureEventDataPacket::TOUCH_TIMEOUT) {
  184. Tail().back().Ack(event_consumed, is_source_touch_event_set_blocking);
  185. if (sequences_.size() == 1 && Tail().size() == 1)
  186. SendAckedEvents();
  187. } else {
  188. DCHECK(!Head().empty());
  189. DCHECK_EQ(Head().front().unique_touch_event_id(), unique_touch_event_id);
  190. Head().front().Ack(event_consumed, is_source_touch_event_set_blocking);
  191. SendAckedEvents();
  192. }
  193. }
  194. void TouchDispositionGestureFilter::SendAckedEvents() {
  195. // Dispatch all packets corresponding to ack'ed touches, as well as
  196. // any pending timeout-based packets.
  197. bool touch_packet_for_current_ack_handled = false;
  198. while (!IsEmpty() && (!Head().empty() || sequences_.size() != 1)) {
  199. if (Head().empty())
  200. PopGestureSequence();
  201. GestureSequence& sequence = Head();
  202. DCHECK_NE(sequence.front().gesture_source(),
  203. GestureEventDataPacket::UNDEFINED);
  204. DCHECK_NE(sequence.front().gesture_source(),
  205. GestureEventDataPacket::INVALID);
  206. GestureEventDataPacket::GestureSource source =
  207. sequence.front().gesture_source();
  208. GestureEventDataPacket::AckState ack_state = sequence.front().ack_state();
  209. if (source != GestureEventDataPacket::TOUCH_TIMEOUT) {
  210. // We've sent all packets which aren't pending their ack.
  211. if (ack_state == GestureEventDataPacket::AckState::PENDING)
  212. break;
  213. state_.OnTouchEventAck(
  214. ack_state == GestureEventDataPacket::AckState::CONSUMED,
  215. IsTouchStartEvent(source));
  216. }
  217. // We need to pop the current sequence before sending the packet, because
  218. // sending the packet could result in this method being re-entered (e.g. on
  219. // Aura, we could trigger a touch-cancel). As popping the sequence destroys
  220. // the packet, we copy the packet before popping it.
  221. touch_packet_for_current_ack_handled = true;
  222. const GestureEventDataPacket packet = sequence.front();
  223. sequence.pop();
  224. FilterAndSendPacket(packet);
  225. }
  226. DCHECK(touch_packet_for_current_ack_handled);
  227. }
  228. bool TouchDispositionGestureFilter::IsEmpty() const {
  229. return sequences_.empty();
  230. }
  231. void TouchDispositionGestureFilter::ResetGestureHandlingState() {
  232. state_ = GestureHandlingState();
  233. }
  234. void TouchDispositionGestureFilter::FilterAndSendPacket(
  235. const GestureEventDataPacket& packet) {
  236. if (packet.gesture_source() == GestureEventDataPacket::TOUCH_SEQUENCE_START) {
  237. CancelTapIfNecessary(packet);
  238. EndScrollIfNecessary(packet);
  239. CancelFlingIfNecessary(packet);
  240. } else if (packet.gesture_source() == GestureEventDataPacket::TOUCH_START) {
  241. CancelTapIfNecessary(packet);
  242. }
  243. int gesture_end_index = -1;
  244. for (size_t i = 0; i < packet.gesture_count(); ++i) {
  245. const GestureEventData& gesture = packet.gesture(i);
  246. DCHECK_GE(gesture.details.type(), ET_GESTURE_TYPE_START);
  247. DCHECK_LE(gesture.details.type(), ET_GESTURE_TYPE_END);
  248. if (state_.Filter(gesture.details.type())) {
  249. CancelTapIfNecessary(packet);
  250. continue;
  251. }
  252. if (gesture.type() == ET_GESTURE_TAP_CANCEL) {
  253. CancelTapIfNecessary(packet);
  254. continue;
  255. }
  256. if (packet.gesture_source() == GestureEventDataPacket::TOUCH_TIMEOUT) {
  257. // Sending a timed gesture could delete |this|, so we need to return
  258. // directly after the |SendGesture| call.
  259. SendGesture(gesture, packet);
  260. // We should not have a timeout gesture and other gestures in the same
  261. // packet.
  262. DCHECK_EQ(1U, packet.gesture_count());
  263. return;
  264. }
  265. // Occasionally scroll or tap cancel events are synthesized when a touch
  266. // sequence has been canceled or terminated, we want to make sure that
  267. // ET_GESTURE_END always happens after them.
  268. if (gesture.type() == ET_GESTURE_END) {
  269. // Make sure there is at most one ET_GESTURE_END event in each packet.
  270. DCHECK_EQ(-1, gesture_end_index);
  271. gesture_end_index = static_cast<int>(i);
  272. continue;
  273. }
  274. SendGesture(gesture, packet);
  275. }
  276. if (packet.gesture_source() ==
  277. GestureEventDataPacket::TOUCH_SEQUENCE_CANCEL) {
  278. EndScrollIfNecessary(packet);
  279. CancelTapIfNecessary(packet);
  280. } else if (packet.gesture_source() ==
  281. GestureEventDataPacket::TOUCH_SEQUENCE_END) {
  282. EndScrollIfNecessary(packet);
  283. }
  284. // Always send the ET_GESTURE_END event as the last one for every touch event.
  285. if (gesture_end_index >= 0)
  286. SendGesture(packet.gesture(gesture_end_index), packet);
  287. }
  288. void TouchDispositionGestureFilter::SendGesture(
  289. const GestureEventData& event,
  290. const GestureEventDataPacket& packet_being_sent) {
  291. DCHECK(event.unique_touch_event_id ==
  292. packet_being_sent.unique_touch_event_id());
  293. // TODO(jdduke): Factor out gesture stream reparation code into a standalone
  294. // utility class.
  295. switch (event.type()) {
  296. case ET_GESTURE_LONG_TAP:
  297. if (!needs_tap_ending_event_)
  298. return;
  299. CancelTapIfNecessary(packet_being_sent);
  300. CancelFlingIfNecessary(packet_being_sent);
  301. break;
  302. case ET_GESTURE_TAP_DOWN:
  303. DCHECK(!needs_tap_ending_event_);
  304. ending_event_motion_event_id_ = event.motion_event_id;
  305. ending_event_primary_tool_type_ = event.primary_tool_type;
  306. needs_show_press_event_ = true;
  307. needs_tap_ending_event_ = true;
  308. break;
  309. case ET_GESTURE_SHOW_PRESS:
  310. if (!needs_show_press_event_)
  311. return;
  312. needs_show_press_event_ = false;
  313. break;
  314. case ET_GESTURE_DOUBLE_TAP:
  315. CancelTapIfNecessary(packet_being_sent);
  316. needs_show_press_event_ = false;
  317. break;
  318. case ET_GESTURE_TAP:
  319. DCHECK(needs_tap_ending_event_);
  320. if (needs_show_press_event_) {
  321. SendGesture(GestureEventData(ET_GESTURE_SHOW_PRESS, event),
  322. packet_being_sent);
  323. DCHECK(!needs_show_press_event_);
  324. }
  325. needs_tap_ending_event_ = false;
  326. break;
  327. case ET_GESTURE_TAP_CANCEL:
  328. needs_show_press_event_ = false;
  329. needs_tap_ending_event_ = false;
  330. break;
  331. case ET_GESTURE_SCROLL_BEGIN:
  332. CancelTapIfNecessary(packet_being_sent);
  333. CancelFlingIfNecessary(packet_being_sent);
  334. EndScrollIfNecessary(packet_being_sent);
  335. ending_event_motion_event_id_ = event.motion_event_id;
  336. ending_event_primary_tool_type_ = event.primary_tool_type;
  337. needs_scroll_ending_event_ = true;
  338. break;
  339. case ET_GESTURE_SCROLL_END:
  340. needs_scroll_ending_event_ = false;
  341. break;
  342. case ET_SCROLL_FLING_START:
  343. CancelFlingIfNecessary(packet_being_sent);
  344. ending_event_motion_event_id_ = event.motion_event_id;
  345. ending_event_primary_tool_type_ = event.primary_tool_type;
  346. needs_fling_ending_event_ = true;
  347. needs_scroll_ending_event_ = false;
  348. break;
  349. case ET_SCROLL_FLING_CANCEL:
  350. needs_fling_ending_event_ = false;
  351. break;
  352. default:
  353. break;
  354. }
  355. client_->ForwardGestureEvent(event);
  356. }
  357. void TouchDispositionGestureFilter::CancelTapIfNecessary(
  358. const GestureEventDataPacket& packet_being_sent) {
  359. if (!needs_tap_ending_event_)
  360. return;
  361. SendGesture(CreateGesture(ET_GESTURE_TAP_CANCEL,
  362. ending_event_motion_event_id_,
  363. ending_event_primary_tool_type_,
  364. packet_being_sent),
  365. packet_being_sent);
  366. DCHECK(!needs_tap_ending_event_);
  367. }
  368. void TouchDispositionGestureFilter::CancelFlingIfNecessary(
  369. const GestureEventDataPacket& packet_being_sent) {
  370. if (!needs_fling_ending_event_)
  371. return;
  372. SendGesture(CreateGesture(ET_SCROLL_FLING_CANCEL,
  373. ending_event_motion_event_id_,
  374. ending_event_primary_tool_type_,
  375. packet_being_sent),
  376. packet_being_sent);
  377. DCHECK(!needs_fling_ending_event_);
  378. }
  379. void TouchDispositionGestureFilter::EndScrollIfNecessary(
  380. const GestureEventDataPacket& packet_being_sent) {
  381. if (!needs_scroll_ending_event_)
  382. return;
  383. SendGesture(CreateGesture(ET_GESTURE_SCROLL_END,
  384. ending_event_motion_event_id_,
  385. ending_event_primary_tool_type_,
  386. packet_being_sent),
  387. packet_being_sent);
  388. DCHECK(!needs_scroll_ending_event_);
  389. }
  390. void TouchDispositionGestureFilter::PopGestureSequence() {
  391. DCHECK(Head().empty());
  392. state_ = GestureHandlingState();
  393. sequences_.pop();
  394. }
  395. TouchDispositionGestureFilter::GestureSequence&
  396. TouchDispositionGestureFilter::Head() {
  397. DCHECK(!sequences_.empty());
  398. return sequences_.front();
  399. }
  400. TouchDispositionGestureFilter::GestureSequence&
  401. TouchDispositionGestureFilter::Tail() {
  402. DCHECK(!sequences_.empty());
  403. return sequences_.back();
  404. }
  405. // TouchDispositionGestureFilter::GestureHandlingState
  406. TouchDispositionGestureFilter::GestureHandlingState::GestureHandlingState()
  407. : start_touch_consumed_(false),
  408. current_touch_consumed_(false) {}
  409. void TouchDispositionGestureFilter::GestureHandlingState::OnTouchEventAck(
  410. bool event_consumed,
  411. bool is_touch_start_event) {
  412. current_touch_consumed_ = event_consumed;
  413. if (event_consumed && is_touch_start_event)
  414. start_touch_consumed_ = true;
  415. }
  416. bool TouchDispositionGestureFilter::GestureHandlingState::Filter(
  417. EventType gesture_type) {
  418. DispositionHandlingInfo disposition_handling_info =
  419. GetDispositionHandlingInfo(gesture_type);
  420. int required_touches = disposition_handling_info.required_touches;
  421. EventType antecedent_event_type =
  422. disposition_handling_info.antecedent_event_type;
  423. if ((required_touches & RT_START && start_touch_consumed_) ||
  424. (required_touches & RT_CURRENT && current_touch_consumed_) ||
  425. (antecedent_event_type != ET_UNKNOWN &&
  426. last_gesture_of_type_dropped_.has_bit(
  427. GetGestureTypeIndex(antecedent_event_type)))) {
  428. last_gesture_of_type_dropped_.mark_bit(GetGestureTypeIndex(gesture_type));
  429. any_gesture_of_type_dropped_.mark_bit(GetGestureTypeIndex(gesture_type));
  430. return true;
  431. }
  432. last_gesture_of_type_dropped_.clear_bit(GetGestureTypeIndex(gesture_type));
  433. return false;
  434. }
  435. bool TouchDispositionGestureFilter::GestureHandlingState::
  436. HasFilteredGestureType(EventType gesture_type) const {
  437. return any_gesture_of_type_dropped_.has_bit(
  438. GetGestureTypeIndex(gesture_type));
  439. }
  440. } // namespace content