gesture_provider.cc 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054
  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/gesture_provider.h"
  5. #include <stddef.h>
  6. #include <cmath>
  7. #include "base/auto_reset.h"
  8. #include "base/memory/raw_ptr.h"
  9. #include "base/time/time.h"
  10. #include "base/trace_event/trace_event.h"
  11. #include "ui/events/event_constants.h"
  12. #include "ui/events/gesture_detection/gesture_configuration.h"
  13. #include "ui/events/gesture_detection/gesture_event_data.h"
  14. #include "ui/events/gesture_detection/gesture_listeners.h"
  15. #include "ui/events/gesture_detection/motion_event.h"
  16. #include "ui/events/gesture_detection/motion_event_generic.h"
  17. #include "ui/events/gesture_detection/scale_gesture_listeners.h"
  18. #include "ui/events/types/event_type.h"
  19. #include "ui/gfx/geometry/point_f.h"
  20. #include "ui/gfx/geometry/vector2d_f.h"
  21. namespace ui {
  22. namespace {
  23. // Double-tap drag zoom sensitivity (speed).
  24. const float kDoubleTapDragZoomSpeed = 0.005f;
  25. const char* GetMotionEventActionName(MotionEvent::Action action) {
  26. switch (action) {
  27. case MotionEvent::Action::NONE:
  28. return "Action::NONE";
  29. case MotionEvent::Action::POINTER_DOWN:
  30. return "Action::POINTER_DOWN";
  31. case MotionEvent::Action::POINTER_UP:
  32. return "Action::POINTER_UP";
  33. case MotionEvent::Action::DOWN:
  34. return "Action::DOWN";
  35. case MotionEvent::Action::UP:
  36. return "Action::UP";
  37. case MotionEvent::Action::CANCEL:
  38. return "Action::CANCEL";
  39. case MotionEvent::Action::MOVE:
  40. return "Action::MOVE";
  41. case MotionEvent::Action::HOVER_ENTER:
  42. return "Action::HOVER_ENTER";
  43. case MotionEvent::Action::HOVER_EXIT:
  44. return "Action::HOVER_EXIT";
  45. case MotionEvent::Action::HOVER_MOVE:
  46. return "Action::HOVER_MOVE";
  47. case MotionEvent::Action::BUTTON_PRESS:
  48. return "Action::BUTTON_PRESS";
  49. case MotionEvent::Action::BUTTON_RELEASE:
  50. return "Action::BUTTON_RELEASE";
  51. }
  52. return "";
  53. }
  54. gfx::RectF ClampBoundingBox(const gfx::RectF& bounds,
  55. float min_length,
  56. float max_length) {
  57. float width = bounds.width();
  58. float height = bounds.height();
  59. if (min_length) {
  60. width = std::max(min_length, width);
  61. height = std::max(min_length, height);
  62. }
  63. if (max_length) {
  64. width = std::min(max_length, width);
  65. height = std::min(max_length, height);
  66. }
  67. const gfx::PointF center = bounds.CenterPoint();
  68. return gfx::RectF(
  69. center.x() - width / 2.f, center.y() - height / 2.f, width, height);
  70. }
  71. } // namespace
  72. // GestureProviderClient:
  73. bool GestureProviderClient::RequiresDoubleTapGestureEvents() const {
  74. return false;
  75. }
  76. // GestureProvider:::Config
  77. GestureProvider::Config::Config()
  78. : display(display::kInvalidDisplayId, gfx::Rect(1, 1)),
  79. double_tap_support_for_platform_enabled(true),
  80. gesture_begin_end_types_enabled(false),
  81. min_gesture_bounds_length(0),
  82. max_gesture_bounds_length(0) {}
  83. GestureProvider::Config::Config(const Config& other) = default;
  84. GestureProvider::Config::~Config() {
  85. }
  86. // GestureProvider::GestureListener
  87. class GestureProvider::GestureListenerImpl : public ScaleGestureListener,
  88. public GestureListener,
  89. public DoubleTapListener {
  90. public:
  91. GestureListenerImpl(const GestureProvider::Config& config,
  92. GestureProviderClient* client,
  93. GestureProvider* gesture_provider)
  94. : config_(config),
  95. client_(client),
  96. gesture_provider_(gesture_provider),
  97. gesture_detector_(config.gesture_detector_config, this, this),
  98. scale_gesture_detector_(config.scale_gesture_detector_config, this),
  99. snap_scroll_controller_(config.gesture_detector_config.touch_slop,
  100. gfx::SizeF(config.display.size())),
  101. ignore_multitouch_zoom_events_(false),
  102. ignore_single_tap_(false),
  103. pinch_event_sent_(false),
  104. scroll_event_sent_(false),
  105. max_diameter_before_show_press_(0),
  106. show_press_event_sent_(false) {}
  107. GestureListenerImpl(const GestureListenerImpl&) = delete;
  108. GestureListenerImpl& operator=(const GestureListenerImpl&) = delete;
  109. void OnTouchEvent(const MotionEvent& event) {
  110. const bool in_scale_gesture = IsScaleGestureDetectionInProgress();
  111. snap_scroll_controller_.SetSnapScrollMode(event, in_scale_gesture);
  112. if (in_scale_gesture)
  113. SetIgnoreSingleTap(true);
  114. const MotionEvent::Action action = event.GetAction();
  115. if (action == MotionEvent::Action::DOWN) {
  116. current_down_action_event_time_ = event.GetEventTime();
  117. DCHECK(gesture_provider_->current_down_event());
  118. current_down_action_unique_touch_event_id_ =
  119. gesture_provider_->current_down_event()->GetUniqueEventId();
  120. current_longpress_time_ = base::TimeTicks();
  121. ignore_single_tap_ = false;
  122. scroll_event_sent_ = false;
  123. pinch_event_sent_ = false;
  124. show_press_event_sent_ = false;
  125. gesture_detector_.set_press_and_hold_enabled(true);
  126. tap_down_point_ = gfx::PointF(event.GetX(), event.GetY());
  127. max_diameter_before_show_press_ = event.GetTouchMajor();
  128. }
  129. gesture_detector_.OnTouchEvent(event,
  130. client_->RequiresDoubleTapGestureEvents());
  131. scale_gesture_detector_.OnTouchEvent(event);
  132. if (action == MotionEvent::Action::UP ||
  133. action == MotionEvent::Action::CANCEL) {
  134. // Note: This call will have no effect if a fling was just generated, as
  135. // |Fling()| will have already signalled an end to touch-scrolling.
  136. if (scroll_event_sent_)
  137. Send(CreateGesture(ET_GESTURE_SCROLL_END, event));
  138. // If this was the last pointer that was canceled or lifted reset the
  139. // |current_down_action_event_time_| to indicate no sequence is going on.
  140. if (action != MotionEvent::Action::CANCEL ||
  141. !GestureConfiguration::GetInstance()
  142. ->single_pointer_cancel_enabled() ||
  143. event.GetPointerCount() == 1)
  144. current_down_action_event_time_ = base::TimeTicks();
  145. } else if (action == MotionEvent::Action::MOVE) {
  146. if (!show_press_event_sent_ && !scroll_event_sent_) {
  147. max_diameter_before_show_press_ =
  148. std::max(max_diameter_before_show_press_, event.GetTouchMajor());
  149. }
  150. }
  151. }
  152. void UpdateStateForEventPost(GestureEventData gesture) {
  153. switch (gesture.type()) {
  154. case ET_GESTURE_LONG_PRESS:
  155. DCHECK(!IsScaleGestureDetectionInProgress());
  156. current_longpress_time_ = gesture.time;
  157. break;
  158. case ET_GESTURE_LONG_TAP:
  159. current_longpress_time_ = base::TimeTicks();
  160. break;
  161. case ET_GESTURE_SCROLL_BEGIN:
  162. DCHECK(!scroll_event_sent_);
  163. scroll_event_sent_ = true;
  164. break;
  165. case ET_GESTURE_SCROLL_END:
  166. DCHECK(scroll_event_sent_);
  167. scroll_event_sent_ = false;
  168. break;
  169. case ET_SCROLL_FLING_START:
  170. DCHECK(scroll_event_sent_);
  171. scroll_event_sent_ = false;
  172. break;
  173. case ET_GESTURE_PINCH_BEGIN:
  174. DCHECK(!pinch_event_sent_);
  175. pinch_event_sent_ = true;
  176. break;
  177. case ET_GESTURE_PINCH_END:
  178. DCHECK(pinch_event_sent_);
  179. pinch_event_sent_ = false;
  180. break;
  181. case ET_GESTURE_SHOW_PRESS:
  182. // It's possible that a double-tap drag zoom (from ScaleGestureDetector)
  183. // will start before the press gesture fires (from GestureDetector), in
  184. // which case the press should simply be dropped.
  185. if (pinch_event_sent_ || scroll_event_sent_)
  186. return;
  187. break;
  188. default:
  189. break;
  190. };
  191. }
  192. // `should_update` indicates whether sending `gesture` should update the
  193. // internal states.
  194. void SendImpl(GestureEventData gesture, bool should_update) {
  195. DCHECK(!gesture.time.is_null());
  196. // The only valid events that should be sent without an active touch
  197. // sequence are SHOW_PRESS, TAP and TAP_CANCEL, potentially triggered by
  198. // the double-tap delay timing out or being cancelled.
  199. DCHECK(!current_down_action_event_time_.is_null() ||
  200. gesture.type() == ET_GESTURE_TAP ||
  201. gesture.type() == ET_GESTURE_SHOW_PRESS ||
  202. gesture.type() == ET_GESTURE_TAP_CANCEL ||
  203. gesture.type() == ET_GESTURE_BEGIN ||
  204. gesture.type() == ET_GESTURE_END);
  205. if (gesture.primary_tool_type == MotionEvent::ToolType::UNKNOWN ||
  206. gesture.primary_tool_type == MotionEvent::ToolType::FINGER) {
  207. gesture.details.set_bounding_box(ClampBoundingBox(
  208. gesture.details.bounding_box_f(), config_.min_gesture_bounds_length,
  209. config_.max_gesture_bounds_length));
  210. }
  211. // Sending one gesture event may trigger propagation of another.
  212. switch (gesture.type()) {
  213. case ET_GESTURE_SCROLL_END:
  214. DCHECK(scroll_event_sent_);
  215. if (pinch_event_sent_)
  216. SendImpl(GestureEventData(ET_GESTURE_PINCH_END, gesture),
  217. should_update);
  218. break;
  219. case ET_GESTURE_PINCH_BEGIN:
  220. DCHECK(!pinch_event_sent_);
  221. if (!scroll_event_sent_ &&
  222. !scale_gesture_detector_.InAnchoredScaleMode()) {
  223. SendImpl(GestureEventData(ET_GESTURE_SCROLL_BEGIN, gesture),
  224. should_update);
  225. }
  226. break;
  227. default:
  228. break;
  229. }
  230. if (should_update) {
  231. UpdateStateForEventPost(gesture);
  232. GestureTouchUMAHistogram::RecordGestureEvent(gesture);
  233. }
  234. client_->OnGestureEvent(gesture);
  235. }
  236. void Send(GestureEventData gesture) {
  237. SendImpl(gesture, /*should_update=*/true);
  238. }
  239. void SendSynthesizedEndEvents() {
  240. MotionEventGeneric generic_cancel_event(MotionEvent::Action::CANCEL,
  241. base::TimeTicks::Now(),
  242. PointerProperties());
  243. // Sending the synthesized end events should not update the internal states.
  244. // Because this function may be called when a new event handler replaces the
  245. // old one. In that scenario, the old event handler is informed of the
  246. // gesture end through the synthesized end events while the new handler
  247. // should handle the incoming gestures.
  248. if (scroll_event_sent_) {
  249. SendImpl(CreateGesture(ET_GESTURE_SCROLL_END, generic_cancel_event),
  250. /*should_update=*/false);
  251. }
  252. SendImpl(CreateGesture(ET_GESTURE_END, generic_cancel_event),
  253. /*should_update=*/false);
  254. }
  255. // ScaleGestureListener implementation.
  256. bool OnScaleBegin(const ScaleGestureDetector& detector,
  257. const MotionEvent& e) override {
  258. if (ignore_multitouch_zoom_events_ && !detector.InAnchoredScaleMode())
  259. return false;
  260. return true;
  261. }
  262. void OnScaleEnd(const ScaleGestureDetector& detector,
  263. const MotionEvent& e) override {
  264. if (!pinch_event_sent_)
  265. return;
  266. Send(CreateGesture(ET_GESTURE_PINCH_END, e));
  267. }
  268. bool OnScale(const ScaleGestureDetector& detector,
  269. const MotionEvent& e) override {
  270. if (ignore_multitouch_zoom_events_ && !detector.InAnchoredScaleMode())
  271. return false;
  272. bool first_scale = false;
  273. if (!pinch_event_sent_) {
  274. first_scale = true;
  275. GestureEventDetails details(ET_GESTURE_PINCH_BEGIN);
  276. details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
  277. details.set_primary_unique_touch_event_id(
  278. current_down_action_unique_touch_event_id_);
  279. Send(CreateGesture(
  280. details, e.GetPointerId(), e.GetToolType(), detector.GetEventTime(),
  281. detector.GetFocusX(), detector.GetFocusY(),
  282. detector.GetFocusX() + e.GetRawOffsetX(),
  283. detector.GetFocusY() + e.GetRawOffsetY(), e.GetPointerCount(),
  284. GetBoundingBox(e, ET_GESTURE_PINCH_BEGIN), e.GetFlags()));
  285. }
  286. if (std::abs(detector.GetCurrentSpan() - detector.GetPreviousSpan()) <
  287. config_.scale_gesture_detector_config.min_pinch_update_span_delta) {
  288. return false;
  289. }
  290. float scale = detector.GetScaleFactor();
  291. if (scale == 1)
  292. return true;
  293. if (detector.InAnchoredScaleMode()) {
  294. // Relative changes in the double-tap scale factor computed by |detector|
  295. // diminish as the touch moves away from the original double-tap focus.
  296. // For historical reasons, Chrome has instead adopted a scale factor
  297. // computation that is invariant to the focal distance, where
  298. // the scale delta remains constant if the touch velocity is constant.
  299. // Note: Because we calculate the scale here manually based on the
  300. // y-span, but the scale factor accounts for slop in the first previous
  301. // span, we manaully reproduce the behavior here for previous span y.
  302. float prev_y = first_scale
  303. ? config_.gesture_detector_config.touch_slop * 2
  304. : detector.GetPreviousSpanY();
  305. float dy = (detector.GetCurrentSpanY() - prev_y) * 0.5f;
  306. scale = std::pow(scale > 1 ? 1.0f + kDoubleTapDragZoomSpeed
  307. : 1.0f - kDoubleTapDragZoomSpeed,
  308. std::abs(dy));
  309. }
  310. GestureEventDetails pinch_details(ET_GESTURE_PINCH_UPDATE);
  311. pinch_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
  312. pinch_details.set_scale(scale);
  313. pinch_details.set_primary_unique_touch_event_id(
  314. current_down_action_unique_touch_event_id_);
  315. Send(CreateGesture(pinch_details,
  316. e.GetPointerId(),
  317. e.GetToolType(),
  318. detector.GetEventTime(),
  319. detector.GetFocusX(),
  320. detector.GetFocusY(),
  321. detector.GetFocusX() + e.GetRawOffsetX(),
  322. detector.GetFocusY() + e.GetRawOffsetY(),
  323. e.GetPointerCount(),
  324. GetBoundingBox(e, pinch_details.type()),
  325. e.GetFlags()));
  326. return true;
  327. }
  328. // GestureListener implementation.
  329. bool OnDown(const MotionEvent& e) override {
  330. GestureEventDetails tap_details(ET_GESTURE_TAP_DOWN);
  331. tap_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
  332. tap_details.set_primary_unique_touch_event_id(
  333. current_down_action_unique_touch_event_id_);
  334. Send(CreateGesture(tap_details, e));
  335. // Return true to indicate that we want to handle touch.
  336. return true;
  337. }
  338. bool OnScroll(const MotionEvent& e1,
  339. const MotionEvent& e2,
  340. const MotionEvent& secondary_pointer_down,
  341. float raw_distance_x,
  342. float raw_distance_y) override {
  343. float distance_x = raw_distance_x;
  344. float distance_y = raw_distance_y;
  345. if (!scroll_event_sent_ && e2.GetPointerCount() < 3) {
  346. // Remove the touch slop region from the first scroll event to avoid a
  347. // jump. Touch slop isn't used for scroll gestures with greater than 2
  348. // pointers down, in those cases we don't subtract the slop.
  349. gfx::Vector2dF delta =
  350. ComputeFirstScrollDelta(e1, e2, secondary_pointer_down);
  351. distance_x = delta.x();
  352. distance_y = delta.y();
  353. }
  354. snap_scroll_controller_.UpdateSnapScrollMode(distance_x, distance_y);
  355. if (snap_scroll_controller_.IsSnappingScrolls()) {
  356. if (snap_scroll_controller_.IsSnapHorizontal())
  357. distance_y = 0;
  358. else
  359. distance_x = 0;
  360. }
  361. if (!distance_x && !distance_y)
  362. return true;
  363. if (!scroll_event_sent_) {
  364. // Note that scroll start hints are in distance traveled, where
  365. // scroll deltas are in the opposite direction.
  366. GestureEventDetails scroll_details(ET_GESTURE_SCROLL_BEGIN, -distance_x,
  367. -distance_y);
  368. scroll_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
  369. scroll_details.set_primary_unique_touch_event_id(
  370. current_down_action_unique_touch_event_id_);
  371. // Scroll focus point always starts with the first touch down point.
  372. scroll_focus_point_.SetPoint(e1.GetX(), e1.GetY());
  373. // Use the co-ordinates from the touch down, as these co-ordinates are
  374. // used to determine which layer the scroll should affect.
  375. Send(CreateGesture(scroll_details, e2.GetPointerId(), e2.GetToolType(),
  376. e2.GetEventTime(), e1.GetX(), e1.GetY(), e1.GetRawX(),
  377. e1.GetRawY(), e2.GetPointerCount(),
  378. GetBoundingBox(e2, scroll_details.type()),
  379. e2.GetFlags()));
  380. DCHECK(scroll_event_sent_);
  381. }
  382. scroll_focus_point_.SetPoint(scroll_focus_point_.x() - raw_distance_x,
  383. scroll_focus_point_.y() - raw_distance_y);
  384. GestureEventDetails scroll_details(ET_GESTURE_SCROLL_UPDATE, -distance_x,
  385. -distance_y);
  386. scroll_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
  387. scroll_details.set_primary_unique_touch_event_id(
  388. current_down_action_unique_touch_event_id_);
  389. const gfx::RectF bounding_box = GetBoundingBox(e2, scroll_details.type());
  390. const gfx::PointF raw_center =
  391. scroll_focus_point_ +
  392. gfx::Vector2dF(e2.GetRawOffsetX(), e2.GetRawOffsetY());
  393. Send(CreateGesture(scroll_details, e2.GetPointerId(), e2.GetToolType(),
  394. e2.GetEventTime(), scroll_focus_point_.x(),
  395. scroll_focus_point_.y(), raw_center.x(), raw_center.y(),
  396. e2.GetPointerCount(), bounding_box, e2.GetFlags()));
  397. return true;
  398. }
  399. bool OnFling(const MotionEvent& e1,
  400. const MotionEvent& e2,
  401. float velocity_x,
  402. float velocity_y) override {
  403. if (snap_scroll_controller_.IsSnappingScrolls()) {
  404. if (snap_scroll_controller_.IsSnapHorizontal()) {
  405. velocity_y = 0;
  406. } else {
  407. velocity_x = 0;
  408. }
  409. }
  410. if (!velocity_x && !velocity_y)
  411. return true;
  412. DCHECK(scroll_event_sent_);
  413. if (!scroll_event_sent_) {
  414. // The native side needs a ET_GESTURE_SCROLL_BEGIN before
  415. // ET_SCROLL_FLING_START to send the fling to the correct target.
  416. // The distance traveled in one second is a reasonable scroll start hint.
  417. GestureEventDetails scroll_details(
  418. ET_GESTURE_SCROLL_BEGIN, velocity_x, velocity_y);
  419. scroll_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
  420. scroll_details.set_primary_unique_touch_event_id(
  421. current_down_action_unique_touch_event_id_);
  422. Send(CreateGesture(scroll_details, e2));
  423. }
  424. GestureEventDetails fling_details(
  425. ET_SCROLL_FLING_START, velocity_x, velocity_y);
  426. fling_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
  427. fling_details.set_primary_unique_touch_event_id(
  428. current_down_action_unique_touch_event_id_);
  429. Send(CreateGesture(fling_details, e2));
  430. return true;
  431. }
  432. bool OnSwipe(const MotionEvent& e1,
  433. const MotionEvent& e2,
  434. float velocity_x,
  435. float velocity_y) override {
  436. GestureEventDetails swipe_details(ET_GESTURE_SWIPE, velocity_x, velocity_y);
  437. swipe_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
  438. swipe_details.set_primary_unique_touch_event_id(
  439. current_down_action_unique_touch_event_id_);
  440. Send(CreateGesture(swipe_details, e2));
  441. return true;
  442. }
  443. bool OnTwoFingerTap(const MotionEvent& e1, const MotionEvent& e2) override {
  444. // The location of the two finger tap event should be the location of the
  445. // primary pointer.
  446. GestureEventDetails two_finger_tap_details(
  447. ET_GESTURE_TWO_FINGER_TAP, e1.GetTouchMajor(), e1.GetTouchMajor());
  448. two_finger_tap_details.set_device_type(
  449. GestureDeviceType::DEVICE_TOUCHSCREEN);
  450. two_finger_tap_details.set_primary_unique_touch_event_id(
  451. current_down_action_unique_touch_event_id_);
  452. Send(CreateGesture(two_finger_tap_details,
  453. e2.GetPointerId(),
  454. e2.GetToolType(),
  455. e2.GetEventTime(),
  456. e1.GetX(),
  457. e1.GetY(),
  458. e1.GetRawX(),
  459. e1.GetRawY(),
  460. e2.GetPointerCount(),
  461. GetBoundingBox(e2, two_finger_tap_details.type()),
  462. e2.GetFlags()));
  463. return true;
  464. }
  465. void OnTapCancel(const MotionEvent& e) override {
  466. GestureEventDetails tap_cancel_details(ET_GESTURE_TAP_CANCEL);
  467. tap_cancel_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
  468. tap_cancel_details.set_primary_unique_touch_event_id(
  469. current_down_action_unique_touch_event_id_);
  470. Send(CreateGesture(ET_GESTURE_TAP_CANCEL, e));
  471. }
  472. void OnShowPress(const MotionEvent& e) override {
  473. GestureEventDetails show_press_details(ET_GESTURE_SHOW_PRESS);
  474. show_press_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
  475. show_press_details.set_primary_unique_touch_event_id(
  476. current_down_action_unique_touch_event_id_);
  477. show_press_event_sent_ = true;
  478. Send(CreateGesture(show_press_details, e));
  479. }
  480. bool OnSingleTapUp(const MotionEvent& e, int tap_count) override {
  481. // This is a hack to address the issue where user hovers
  482. // over a link for longer than double_tap_timeout_, then
  483. // OnSingleTapConfirmed() is not triggered. But we still
  484. // want to trigger the tap event at UP. So we override
  485. // OnSingleTapUp() in this case. This assumes singleTapUp
  486. // gets always called before singleTapConfirmed.
  487. if (!ignore_single_tap_) {
  488. if (e.GetEventTime() - current_down_action_event_time_ >
  489. config_.gesture_detector_config.double_tap_timeout) {
  490. return OnSingleTapImpl(e, tap_count);
  491. } else if (!IsDoubleTapEnabled()) {
  492. // If double-tap has been disabled, there is no need to wait
  493. // for the double-tap timeout.
  494. return OnSingleTapImpl(e, tap_count);
  495. } else {
  496. // Notify Blink about this tapUp event anyway, when none of the above
  497. // conditions applied.
  498. Send(CreateTapGesture(ET_GESTURE_TAP_UNCONFIRMED, e, 1));
  499. }
  500. }
  501. if (e.GetAction() == MotionEvent::Action::UP &&
  502. !current_longpress_time_.is_null() &&
  503. !IsScaleGestureDetectionInProgress()) {
  504. GestureEventDetails long_tap_details(ET_GESTURE_LONG_TAP);
  505. long_tap_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
  506. long_tap_details.set_primary_unique_touch_event_id(
  507. current_down_action_unique_touch_event_id_);
  508. Send(CreateGesture(long_tap_details, e));
  509. return true;
  510. }
  511. return false;
  512. }
  513. // DoubleTapListener implementation.
  514. bool OnSingleTapConfirmed(const MotionEvent& e) override {
  515. return OnSingleTapImpl(e, 1);
  516. }
  517. bool OnDoubleTap(const MotionEvent& e) override {
  518. return scale_gesture_detector_.OnDoubleTap(e);
  519. }
  520. bool OnDoubleTapEvent(const MotionEvent& e) override {
  521. switch (e.GetAction()) {
  522. case MotionEvent::Action::DOWN:
  523. gesture_detector_.set_press_and_hold_enabled(false);
  524. break;
  525. case MotionEvent::Action::UP:
  526. if (!IsPinchInProgress() && !IsScrollInProgress()) {
  527. Send(CreateTapGesture(ET_GESTURE_DOUBLE_TAP, e, 1));
  528. return true;
  529. }
  530. break;
  531. default:
  532. break;
  533. }
  534. return false;
  535. }
  536. void OnShortPress(const MotionEvent& e) override {
  537. DCHECK(!IsDoubleTapInProgress());
  538. GestureEventDetails short_press_details(ET_GESTURE_SHORT_PRESS);
  539. short_press_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
  540. short_press_details.set_primary_unique_touch_event_id(
  541. current_down_action_unique_touch_event_id_);
  542. Send(CreateGesture(short_press_details, e));
  543. }
  544. void OnLongPress(const MotionEvent& e) override {
  545. DCHECK(!IsDoubleTapInProgress());
  546. SetIgnoreSingleTap(true);
  547. GestureEventDetails long_press_details(ET_GESTURE_LONG_PRESS);
  548. long_press_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
  549. long_press_details.set_primary_unique_touch_event_id(
  550. current_down_action_unique_touch_event_id_);
  551. Send(CreateGesture(long_press_details, e));
  552. }
  553. GestureEventData CreateGesture(const GestureEventDetails& details,
  554. int motion_event_id,
  555. MotionEvent::ToolType primary_tool_type,
  556. base::TimeTicks time,
  557. float x,
  558. float y,
  559. float raw_x,
  560. float raw_y,
  561. size_t touch_point_count,
  562. const gfx::RectF& bounding_box,
  563. int flags) const {
  564. return GestureEventData(details,
  565. motion_event_id,
  566. primary_tool_type,
  567. time,
  568. x,
  569. y,
  570. raw_x,
  571. raw_y,
  572. touch_point_count,
  573. bounding_box,
  574. flags,
  575. 0U);
  576. }
  577. GestureEventData CreateGesture(const GestureEventDetails& details,
  578. const MotionEvent& event) const {
  579. return GestureEventData(details, event.GetPointerId(), event.GetToolType(),
  580. event.GetEventTime(), event.GetX(), event.GetY(),
  581. event.GetRawX(), event.GetRawY(),
  582. event.GetPointerCount(),
  583. GetBoundingBox(event, details.type()),
  584. event.GetFlags(), event.GetUniqueEventId());
  585. }
  586. GestureEventData CreateGesture(EventType type,
  587. const MotionEvent& event) const {
  588. GestureEventDetails details(type);
  589. details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
  590. details.set_primary_unique_touch_event_id(
  591. current_down_action_unique_touch_event_id_);
  592. return CreateGesture(details, event);
  593. }
  594. GestureEventData CreateTapGesture(EventType type,
  595. const MotionEvent& event,
  596. int tap_count) const {
  597. DCHECK_GE(tap_count, 0);
  598. GestureEventDetails details(type);
  599. details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
  600. details.set_tap_count(tap_count);
  601. details.set_primary_unique_touch_event_id(
  602. current_down_action_unique_touch_event_id_);
  603. return CreateGesture(details, event);
  604. }
  605. gfx::RectF GetBoundingBox(const MotionEvent& event, EventType type) const {
  606. // Can't use gfx::RectF::Union, as it ignores touches with a radius of 0.
  607. float left = std::numeric_limits<float>::max();
  608. float top = std::numeric_limits<float>::max();
  609. float right = -std::numeric_limits<float>::max();
  610. float bottom = -std::numeric_limits<float>::max();
  611. for (size_t i = 0; i < event.GetPointerCount(); ++i) {
  612. float x, y, diameter;
  613. // Only for the show press and tap events, the bounding box is calculated
  614. // based on the touch start point and the maximum diameter before the
  615. // show press event is sent.
  616. if (type == ET_GESTURE_SHOW_PRESS || type == ET_GESTURE_TAP ||
  617. type == ET_GESTURE_TAP_UNCONFIRMED) {
  618. DCHECK_EQ(0U, i);
  619. diameter = max_diameter_before_show_press_;
  620. x = tap_down_point_.x();
  621. y = tap_down_point_.y();
  622. } else {
  623. diameter = event.GetTouchMajor(i);
  624. x = event.GetX(i);
  625. y = event.GetY(i);
  626. }
  627. x = x - diameter / 2;
  628. y = y - diameter / 2;
  629. left = std::min(left, x);
  630. right = std::max(right, x + diameter);
  631. top = std::min(top, y);
  632. bottom = std::max(bottom, y + diameter);
  633. }
  634. return gfx::RectF(left, top, right - left, bottom - top);
  635. }
  636. void SetDoubleTapEnabled(bool enabled) {
  637. DCHECK(!IsDoubleTapInProgress());
  638. gesture_detector_.SetDoubleTapListener(enabled ? this : NULL);
  639. }
  640. void SetMultiTouchZoomEnabled(bool enabled) {
  641. // Note that returning false from |OnScaleBegin()| or |OnScale()| prevents
  642. // the detector from emitting further scale updates for the current touch
  643. // sequence. Thus, if multitouch events are enabled in the middle of a
  644. // gesture, it will only take effect with the next gesture.
  645. ignore_multitouch_zoom_events_ = !enabled;
  646. }
  647. bool IsDoubleTapInProgress() const {
  648. return gesture_detector_.is_double_tapping() ||
  649. (IsScaleGestureDetectionInProgress() && InAnchoredScaleMode());
  650. }
  651. bool IsScrollInProgress() const { return scroll_event_sent_; }
  652. bool IsPinchInProgress() const { return pinch_event_sent_; }
  653. private:
  654. bool OnSingleTapImpl(const MotionEvent& e, int tap_count) {
  655. // Long taps in the edges of the screen have their events delayed by
  656. // ContentViewHolder for tab swipe operations. As a consequence of the delay
  657. // this method might be called after receiving the up event.
  658. // These corner cases should be ignored.
  659. if (ignore_single_tap_)
  660. return true;
  661. ignore_single_tap_ = true;
  662. Send(CreateTapGesture(ET_GESTURE_TAP, e, tap_count));
  663. return true;
  664. }
  665. bool IsScaleGestureDetectionInProgress() const {
  666. return scale_gesture_detector_.IsInProgress();
  667. }
  668. bool InAnchoredScaleMode() const {
  669. return scale_gesture_detector_.InAnchoredScaleMode();
  670. }
  671. bool IsDoubleTapEnabled() const {
  672. return gesture_detector_.has_doubletap_listener() &&
  673. client_->RequiresDoubleTapGestureEvents();
  674. }
  675. void SetIgnoreSingleTap(bool value) { ignore_single_tap_ = value; }
  676. gfx::Vector2dF SubtractSlopRegion(const float dx, const float dy) {
  677. float distance = std::sqrt(dx * dx + dy * dy);
  678. float epsilon = 1e-3f;
  679. if (distance > epsilon) {
  680. float ratio =
  681. std::max(0.f, distance - config_.gesture_detector_config.touch_slop) /
  682. distance;
  683. gfx::Vector2dF delta(dx * ratio, dy * ratio);
  684. return delta;
  685. }
  686. gfx::Vector2dF delta(dx, dy);
  687. return delta;
  688. }
  689. // When any of the currently down pointers exceeds its slop region
  690. // for the first time, scroll delta is adjusted.
  691. // The new deltas are calculated for each pointer individually,
  692. // and the final scroll delta is the average over all delta values.
  693. gfx::Vector2dF ComputeFirstScrollDelta(
  694. const MotionEvent& ev1,
  695. const MotionEvent& ev2,
  696. const MotionEvent& secondary_pointer_down) {
  697. // If there are more than two down pointers, tapping is not possible,
  698. // so Slop region is not deducted.
  699. DCHECK(ev2.GetPointerCount() < 3);
  700. gfx::Vector2dF delta(0, 0);
  701. for (size_t i = 0; i < ev2.GetPointerCount(); i++) {
  702. const int pointer_id = ev2.GetPointerId(i);
  703. const MotionEvent* source_pointer_down_event =
  704. gesture_detector_.GetSourcePointerDownEvent(
  705. ev1, &secondary_pointer_down, pointer_id);
  706. if (!source_pointer_down_event)
  707. continue;
  708. int source_index =
  709. source_pointer_down_event->FindPointerIndexOfId(pointer_id);
  710. DCHECK_GE(source_index, 0);
  711. if (source_index < 0)
  712. continue;
  713. float dx = source_pointer_down_event->GetX(source_index) - ev2.GetX(i);
  714. float dy = source_pointer_down_event->GetY(source_index) - ev2.GetY(i);
  715. delta += SubtractSlopRegion(dx, dy);
  716. }
  717. delta.Scale(1.0 / ev2.GetPointerCount());
  718. return delta;
  719. }
  720. const GestureProvider::Config config_;
  721. const raw_ptr<GestureProviderClient> client_;
  722. const raw_ptr<GestureProvider> gesture_provider_;
  723. GestureDetector gesture_detector_;
  724. ScaleGestureDetector scale_gesture_detector_;
  725. SnapScrollController snap_scroll_controller_;
  726. // Keeps track of the event time of the first down action in current touch
  727. // sequence.
  728. base::TimeTicks current_down_action_event_time_;
  729. // Keeps track of the unique touch event id of the first down action in
  730. // current touch sequence.
  731. int current_down_action_unique_touch_event_id_;
  732. // Keeps track of the current GESTURE_LONG_PRESS event. If a context menu is
  733. // opened after a GESTURE_LONG_PRESS, this is used to insert a
  734. // GESTURE_TAP_CANCEL for removing any ::active styling.
  735. base::TimeTicks current_longpress_time_;
  736. // Completely silence multi-touch (pinch) scaling events. Used in WebView when
  737. // zoom support is turned off.
  738. bool ignore_multitouch_zoom_events_;
  739. // TODO(klobag): This is to avoid a bug in GestureDetector. With multi-touch,
  740. // always_in_tap_region_ is not reset. So when the last finger is up,
  741. // |OnSingleTapUp()| will be mistakenly fired.
  742. bool ignore_single_tap_;
  743. // Tracks whether {PINCH|SCROLL}_BEGIN events have been forwarded for the
  744. // current touch sequence.
  745. bool pinch_event_sent_;
  746. bool scroll_event_sent_;
  747. // Only track the maximum diameter before the show press event has been
  748. // sent and a tap must still be possible for this touch sequence.
  749. float max_diameter_before_show_press_;
  750. gfx::PointF tap_down_point_;
  751. // Tracks whether an ET_GESTURE_SHOW_PRESS event has been sent for this touch
  752. // sequence.
  753. bool show_press_event_sent_;
  754. // The scroll focus point is set to the first touch down point when scroll
  755. // begins and is later updated based on the delta of touch points.
  756. gfx::PointF scroll_focus_point_;
  757. };
  758. // GestureProvider
  759. GestureProvider::GestureProvider(const Config& config,
  760. GestureProviderClient* client)
  761. : double_tap_support_for_page_(true),
  762. double_tap_support_for_platform_(
  763. config.double_tap_support_for_platform_enabled),
  764. gesture_begin_end_types_enabled_(config.gesture_begin_end_types_enabled) {
  765. DCHECK(client);
  766. DCHECK(!config.min_gesture_bounds_length ||
  767. !config.max_gesture_bounds_length ||
  768. config.min_gesture_bounds_length <= config.max_gesture_bounds_length);
  769. TRACE_EVENT0("input", "GestureProvider::InitGestureDetectors");
  770. gesture_listener_ =
  771. std::make_unique<GestureListenerImpl>(config, client, this);
  772. UpdateDoubleTapDetectionSupport();
  773. }
  774. GestureProvider::~GestureProvider() {
  775. }
  776. bool GestureProvider::OnTouchEvent(const MotionEvent& event) {
  777. TRACE_EVENT1("input",
  778. "GestureProvider::OnTouchEvent",
  779. "action",
  780. GetMotionEventActionName(event.GetAction()));
  781. DCHECK_NE(0u, event.GetPointerCount());
  782. // We record the histograms before the |CanHandle()| call below because we
  783. // want to check the event stream before gesture processing takes place. For
  784. // example, we want to see |MotionEvent::Action::UP| event even for a panning
  785. // gesture where the UP is not dispatched to content.
  786. uma_histogram_.RecordTouchEvent(event);
  787. if (!CanHandle(event))
  788. return false;
  789. OnTouchEventHandlingBegin(event);
  790. gesture_listener_->OnTouchEvent(event);
  791. OnTouchEventHandlingEnd(event);
  792. return true;
  793. }
  794. void GestureProvider::ResetDetection() {
  795. MotionEventGeneric generic_cancel_event(
  796. MotionEvent::Action::CANCEL, base::TimeTicks::Now(), PointerProperties());
  797. OnTouchEvent(generic_cancel_event);
  798. }
  799. void GestureProvider::SetMultiTouchZoomSupportEnabled(bool enabled) {
  800. gesture_listener_->SetMultiTouchZoomEnabled(enabled);
  801. }
  802. void GestureProvider::SetDoubleTapSupportForPlatformEnabled(bool enabled) {
  803. if (double_tap_support_for_platform_ == enabled)
  804. return;
  805. double_tap_support_for_platform_ = enabled;
  806. UpdateDoubleTapDetectionSupport();
  807. }
  808. void GestureProvider::SetDoubleTapSupportForPageEnabled(bool enabled) {
  809. if (double_tap_support_for_page_ == enabled)
  810. return;
  811. double_tap_support_for_page_ = enabled;
  812. UpdateDoubleTapDetectionSupport();
  813. }
  814. bool GestureProvider::IsScrollInProgress() const {
  815. return gesture_listener_->IsScrollInProgress();
  816. }
  817. bool GestureProvider::IsPinchInProgress() const {
  818. return gesture_listener_->IsPinchInProgress();
  819. }
  820. bool GestureProvider::IsDoubleTapInProgress() const {
  821. return gesture_listener_->IsDoubleTapInProgress();
  822. }
  823. void GestureProvider::SendSynthesizedEndEvents() {
  824. gesture_listener_->SendSynthesizedEndEvents();
  825. }
  826. bool GestureProvider::CanHandle(const MotionEvent& event) const {
  827. // Aura requires one cancel event per touch point, whereas Android requires
  828. // one cancel event per touch sequence. Thus we need to allow extra cancel
  829. // events.
  830. return current_down_event_ ||
  831. event.GetAction() == MotionEvent::Action::DOWN ||
  832. event.GetAction() == MotionEvent::Action::CANCEL;
  833. }
  834. void GestureProvider::OnTouchEventHandlingBegin(const MotionEvent& event) {
  835. switch (event.GetAction()) {
  836. case MotionEvent::Action::DOWN:
  837. current_down_event_ = event.Clone();
  838. if (gesture_begin_end_types_enabled_) {
  839. GestureEventDetails details(ET_GESTURE_BEGIN);
  840. details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
  841. details.set_primary_unique_touch_event_id(event.GetUniqueEventId());
  842. gesture_listener_->Send(
  843. gesture_listener_->CreateGesture(details, event));
  844. }
  845. break;
  846. case MotionEvent::Action::POINTER_DOWN:
  847. if (gesture_begin_end_types_enabled_) {
  848. const int action_index = event.GetActionIndex();
  849. GestureEventDetails details(ET_GESTURE_BEGIN);
  850. details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
  851. details.set_primary_unique_touch_event_id(event.GetUniqueEventId());
  852. gesture_listener_->Send(gesture_listener_->CreateGesture(
  853. details, event.GetPointerId(), event.GetToolType(),
  854. event.GetEventTime(), event.GetX(action_index),
  855. event.GetY(action_index), event.GetRawX(action_index),
  856. event.GetRawY(action_index), event.GetPointerCount(),
  857. gesture_listener_->GetBoundingBox(event, ET_GESTURE_BEGIN),
  858. event.GetFlags()));
  859. }
  860. break;
  861. case MotionEvent::Action::POINTER_UP:
  862. case MotionEvent::Action::UP:
  863. case MotionEvent::Action::CANCEL:
  864. case MotionEvent::Action::MOVE:
  865. break;
  866. case MotionEvent::Action::NONE:
  867. case MotionEvent::Action::HOVER_ENTER:
  868. case MotionEvent::Action::HOVER_EXIT:
  869. case MotionEvent::Action::HOVER_MOVE:
  870. case MotionEvent::Action::BUTTON_PRESS:
  871. case MotionEvent::Action::BUTTON_RELEASE:
  872. NOTREACHED();
  873. break;
  874. }
  875. }
  876. void GestureProvider::OnTouchEventHandlingEnd(const MotionEvent& event) {
  877. switch (event.GetAction()) {
  878. case MotionEvent::Action::UP:
  879. case MotionEvent::Action::CANCEL: {
  880. if (gesture_begin_end_types_enabled_) {
  881. GestureEventDetails details(ET_GESTURE_END);
  882. details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
  883. if (current_down_event_) {
  884. details.set_primary_unique_touch_event_id(
  885. current_down_event_->GetUniqueEventId());
  886. }
  887. gesture_listener_->Send(
  888. gesture_listener_->CreateGesture(details, event));
  889. }
  890. if (event.GetAction() != MotionEvent::Action::CANCEL ||
  891. !GestureConfiguration::GetInstance()
  892. ->single_pointer_cancel_enabled() ||
  893. event.GetPointerCount() == 1)
  894. current_down_event_.reset();
  895. UpdateDoubleTapDetectionSupport();
  896. break;
  897. }
  898. case MotionEvent::Action::POINTER_UP:
  899. if (gesture_begin_end_types_enabled_) {
  900. GestureEventDetails details(ET_GESTURE_END);
  901. details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
  902. if (current_down_event_) {
  903. details.set_primary_unique_touch_event_id(
  904. current_down_event_->GetUniqueEventId());
  905. }
  906. gesture_listener_->Send(
  907. gesture_listener_->CreateGesture(details, event));
  908. }
  909. break;
  910. case MotionEvent::Action::DOWN:
  911. case MotionEvent::Action::POINTER_DOWN:
  912. case MotionEvent::Action::MOVE:
  913. break;
  914. case MotionEvent::Action::NONE:
  915. case MotionEvent::Action::HOVER_ENTER:
  916. case MotionEvent::Action::HOVER_EXIT:
  917. case MotionEvent::Action::HOVER_MOVE:
  918. case MotionEvent::Action::BUTTON_PRESS:
  919. case MotionEvent::Action::BUTTON_RELEASE:
  920. NOTREACHED();
  921. break;
  922. }
  923. }
  924. void GestureProvider::UpdateDoubleTapDetectionSupport() {
  925. // The GestureDetector requires that any provided DoubleTapListener remain
  926. // attached to it for the duration of a touch sequence. Defer any potential
  927. // null'ing of the listener until the sequence has ended.
  928. if (current_down_event_)
  929. return;
  930. const bool double_tap_enabled =
  931. double_tap_support_for_page_ && double_tap_support_for_platform_;
  932. gesture_listener_->SetDoubleTapEnabled(double_tap_enabled);
  933. }
  934. } // namespace ui