// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/events/gesture_detection/gesture_provider.h"

#include <stddef.h>

#include <cmath>

#include "base/auto_reset.h"
#include "base/macros.h"
#include "base/trace_event/trace_event.h"
#include "ui/events/event_constants.h"
#include "ui/events/gesture_detection/gesture_configuration.h"
#include "ui/events/gesture_detection/gesture_event_data.h"
#include "ui/events/gesture_detection/gesture_listeners.h"
#include "ui/events/gesture_detection/motion_event.h"
#include "ui/events/gesture_detection/motion_event_generic.h"
#include "ui/events/gesture_detection/scale_gesture_listeners.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/vector2d_f.h"

namespace ui {
namespace {

// Double-tap drag zoom sensitivity (speed).
const float kDoubleTapDragZoomSpeed = 0.005f;

const char* GetMotionEventActionName(MotionEvent::Action action) {
  switch (action) {
    case MotionEvent::Action::NONE:
      return "Action::NONE";
    case MotionEvent::Action::POINTER_DOWN:
      return "Action::POINTER_DOWN";
    case MotionEvent::Action::POINTER_UP:
      return "Action::POINTER_UP";
    case MotionEvent::Action::DOWN:
      return "Action::DOWN";
    case MotionEvent::Action::UP:
      return "Action::UP";
    case MotionEvent::Action::CANCEL:
      return "Action::CANCEL";
    case MotionEvent::Action::MOVE:
      return "Action::MOVE";
    case MotionEvent::Action::HOVER_ENTER:
      return "Action::HOVER_ENTER";
    case MotionEvent::Action::HOVER_EXIT:
      return "Action::HOVER_EXIT";
    case MotionEvent::Action::HOVER_MOVE:
      return "Action::HOVER_MOVE";
    case MotionEvent::Action::BUTTON_PRESS:
      return "Action::BUTTON_PRESS";
    case MotionEvent::Action::BUTTON_RELEASE:
      return "Action::BUTTON_RELEASE";
  }
  return "";
}

gfx::RectF ClampBoundingBox(const gfx::RectF& bounds,
                            float min_length,
                            float max_length) {
  float width = bounds.width();
  float height = bounds.height();
  if (min_length) {
    width = std::max(min_length, width);
    height = std::max(min_length, height);
  }
  if (max_length) {
    width = std::min(max_length, width);
    height = std::min(max_length, height);
  }
  const gfx::PointF center = bounds.CenterPoint();
  return gfx::RectF(
      center.x() - width / 2.f, center.y() - height / 2.f, width, height);
}

}  // namespace

// GestureProviderClient:

bool GestureProviderClient::RequiresDoubleTapGestureEvents() const {
  return false;
}

// GestureProvider:::Config

GestureProvider::Config::Config()
    : display(display::kInvalidDisplayId, gfx::Rect(1, 1)),
      double_tap_support_for_platform_enabled(true),
      gesture_begin_end_types_enabled(false),
      min_gesture_bounds_length(0),
      max_gesture_bounds_length(0) {}

GestureProvider::Config::Config(const Config& other) = default;

GestureProvider::Config::~Config() {
}

// GestureProvider::GestureListener

class GestureProvider::GestureListenerImpl : public ScaleGestureListener,
                                             public GestureListener,
                                             public DoubleTapListener {
 public:
  GestureListenerImpl(const GestureProvider::Config& config,
                      GestureProviderClient* client)
      : config_(config),
        client_(client),
        gesture_detector_(config.gesture_detector_config, this, this),
        scale_gesture_detector_(config.scale_gesture_detector_config, this),
        snap_scroll_controller_(config.gesture_detector_config.touch_slop,
                                gfx::SizeF(config.display.size())),
        ignore_multitouch_zoom_events_(false),
        ignore_single_tap_(false),
        pinch_event_sent_(false),
        scroll_event_sent_(false),
        max_diameter_before_show_press_(0),
        show_press_event_sent_(false) {}

  void OnTouchEvent(const MotionEvent& event) {
    const bool in_scale_gesture = IsScaleGestureDetectionInProgress();
    snap_scroll_controller_.SetSnapScrollMode(event, in_scale_gesture);
    if (in_scale_gesture)
      SetIgnoreSingleTap(true);

    const MotionEvent::Action action = event.GetAction();
    if (action == MotionEvent::Action::DOWN) {
      current_down_action_event_time_ = event.GetEventTime();
      current_longpress_time_ = base::TimeTicks();
      ignore_single_tap_ = false;
      scroll_event_sent_ = false;
      pinch_event_sent_ = false;
      show_press_event_sent_ = false;
      gesture_detector_.set_longpress_enabled(true);
      tap_down_point_ = gfx::PointF(event.GetX(), event.GetY());
      max_diameter_before_show_press_ = event.GetTouchMajor();
    }
    gesture_detector_.OnTouchEvent(event,
                                   client_->RequiresDoubleTapGestureEvents());
    scale_gesture_detector_.OnTouchEvent(event);

    if (action == MotionEvent::Action::UP ||
        action == MotionEvent::Action::CANCEL) {
      // Note: This call will have no effect if a fling was just generated, as
      // |Fling()| will have already signalled an end to touch-scrolling.
      if (scroll_event_sent_)
        Send(CreateGesture(ET_GESTURE_SCROLL_END, event));

      // If this was the last pointer that was canceled or lifted reset the
      // |current_down_action_event_time_| to indicate no sequence is going on.
      if (action != MotionEvent::Action::CANCEL ||
          !GestureConfiguration::GetInstance()
               ->single_pointer_cancel_enabled() ||
          event.GetPointerCount() == 1)
        current_down_action_event_time_ = base::TimeTicks();
    } else if (action == MotionEvent::Action::MOVE) {
      if (!show_press_event_sent_ && !scroll_event_sent_) {
        max_diameter_before_show_press_ =
            std::max(max_diameter_before_show_press_, event.GetTouchMajor());
      }
    }
  }

  void Send(GestureEventData gesture) {
    DCHECK(!gesture.time.is_null());
    // The only valid events that should be sent without an active touch
    // sequence are SHOW_PRESS, TAP and TAP_CANCEL, potentially triggered by
    // the double-tap delay timing out or being cancelled.
    DCHECK(!current_down_action_event_time_.is_null() ||
           gesture.type() == ET_GESTURE_TAP ||
           gesture.type() == ET_GESTURE_SHOW_PRESS ||
           gesture.type() == ET_GESTURE_TAP_CANCEL ||
           gesture.type() == ET_GESTURE_BEGIN ||
           gesture.type() == ET_GESTURE_END);

    if (gesture.primary_tool_type == MotionEvent::ToolType::UNKNOWN ||
        gesture.primary_tool_type == MotionEvent::ToolType::FINGER) {
      gesture.details.set_bounding_box(
          ClampBoundingBox(gesture.details.bounding_box_f(),
                           config_.min_gesture_bounds_length,
                           config_.max_gesture_bounds_length));
    }

    switch (gesture.type()) {
      case ET_GESTURE_LONG_PRESS:
        DCHECK(!IsScaleGestureDetectionInProgress());
        current_longpress_time_ = gesture.time;
        break;
      case ET_GESTURE_LONG_TAP:
        current_longpress_time_ = base::TimeTicks();
        break;
      case ET_GESTURE_SCROLL_BEGIN:
        DCHECK(!scroll_event_sent_);
        scroll_event_sent_ = true;
        break;
      case ET_GESTURE_SCROLL_END:
        DCHECK(scroll_event_sent_);
        if (pinch_event_sent_)
          Send(GestureEventData(ET_GESTURE_PINCH_END, gesture));
        scroll_event_sent_ = false;
        break;
      case ET_SCROLL_FLING_START:
        DCHECK(scroll_event_sent_);
        scroll_event_sent_ = false;
        break;
      case ET_GESTURE_PINCH_BEGIN:
        DCHECK(!pinch_event_sent_);
        if (!scroll_event_sent_ &&
            !scale_gesture_detector_.InAnchoredScaleMode()) {
          Send(GestureEventData(ET_GESTURE_SCROLL_BEGIN, gesture));
        }
        pinch_event_sent_ = true;
        break;
      case ET_GESTURE_PINCH_END:
        DCHECK(pinch_event_sent_);
        pinch_event_sent_ = false;
        break;
      case ET_GESTURE_SHOW_PRESS:
        // It's possible that a double-tap drag zoom (from ScaleGestureDetector)
        // will start before the press gesture fires (from GestureDetector), in
        // which case the press should simply be dropped.
        if (pinch_event_sent_ || scroll_event_sent_)
          return;
        break;
      default:
        break;
    };

    client_->OnGestureEvent(gesture);
    GestureTouchUMAHistogram::RecordGestureEvent(gesture);
  }

  // ScaleGestureListener implementation.
  bool OnScaleBegin(const ScaleGestureDetector& detector,
                    const MotionEvent& e) override {
    if (ignore_multitouch_zoom_events_ && !detector.InAnchoredScaleMode())
      return false;
    return true;
  }

  void OnScaleEnd(const ScaleGestureDetector& detector,
                  const MotionEvent& e) override {
    if (!pinch_event_sent_)
      return;
    Send(CreateGesture(ET_GESTURE_PINCH_END, e));
  }

  bool OnScale(const ScaleGestureDetector& detector,
               const MotionEvent& e) override {
    if (ignore_multitouch_zoom_events_ && !detector.InAnchoredScaleMode())
      return false;
    bool first_scale = false;
    if (!pinch_event_sent_) {
      first_scale = true;
      Send(CreateGesture(ET_GESTURE_PINCH_BEGIN,
                         e.GetPointerId(),
                         e.GetToolType(),
                         detector.GetEventTime(),
                         detector.GetFocusX(),
                         detector.GetFocusY(),
                         detector.GetFocusX() + e.GetRawOffsetX(),
                         detector.GetFocusY() + e.GetRawOffsetY(),
                         e.GetPointerCount(),
                         GetBoundingBox(e, ET_GESTURE_PINCH_BEGIN),
                         e.GetFlags()));
    }

    if (std::abs(detector.GetCurrentSpan() - detector.GetPreviousSpan()) <
        config_.scale_gesture_detector_config.min_pinch_update_span_delta) {
      return false;
    }

    float scale = detector.GetScaleFactor();
    if (scale == 1)
      return true;

    if (detector.InAnchoredScaleMode()) {
      // Relative changes in the double-tap scale factor computed by |detector|
      // diminish as the touch moves away from the original double-tap focus.
      // For historical reasons, Chrome has instead adopted a scale factor
      // computation that is invariant to the focal distance, where
      // the scale delta remains constant if the touch velocity is constant.
      // Note: Because we calculate the scale here manually based on the
      // y-span, but the scale factor accounts for slop in the first previous
      // span, we manaully reproduce the behavior here for previous span y.
      float prev_y = first_scale
                         ? config_.gesture_detector_config.touch_slop * 2
                         : detector.GetPreviousSpanY();
      float dy = (detector.GetCurrentSpanY() - prev_y) * 0.5f;
      scale = std::pow(scale > 1 ? 1.0f + kDoubleTapDragZoomSpeed
                                 : 1.0f - kDoubleTapDragZoomSpeed,
                       std::abs(dy));
    }
    GestureEventDetails pinch_details(ET_GESTURE_PINCH_UPDATE);
    pinch_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
    pinch_details.set_scale(scale);
    Send(CreateGesture(pinch_details,
                       e.GetPointerId(),
                       e.GetToolType(),
                       detector.GetEventTime(),
                       detector.GetFocusX(),
                       detector.GetFocusY(),
                       detector.GetFocusX() + e.GetRawOffsetX(),
                       detector.GetFocusY() + e.GetRawOffsetY(),
                       e.GetPointerCount(),
                       GetBoundingBox(e, pinch_details.type()),
                       e.GetFlags()));
    return true;
  }

  // GestureListener implementation.
  bool OnDown(const MotionEvent& e) override {
    GestureEventDetails tap_details(ET_GESTURE_TAP_DOWN);
    tap_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
    Send(CreateGesture(tap_details, e));

    // Return true to indicate that we want to handle touch.
    return true;
  }

  bool OnScroll(const MotionEvent& e1,
                const MotionEvent& e2,
                const MotionEvent& secondary_pointer_down,
                float raw_distance_x,
                float raw_distance_y) override {
    float distance_x = raw_distance_x;
    float distance_y = raw_distance_y;
    if (!scroll_event_sent_ && e2.GetPointerCount() < 3) {
      // Remove the touch slop region from the first scroll event to avoid a
      // jump. Touch slop isn't used for scroll gestures with greater than 2
      // pointers down, in those cases we don't subtract the slop.
      gfx::Vector2dF delta =
          ComputeFirstScrollDelta(e1, e2, secondary_pointer_down);
      distance_x = delta.x();
      distance_y = delta.y();
    }

    snap_scroll_controller_.UpdateSnapScrollMode(distance_x, distance_y);
    if (snap_scroll_controller_.IsSnappingScrolls()) {
      if (snap_scroll_controller_.IsSnapHorizontal())
        distance_y = 0;
      else
        distance_x = 0;
    }

    if (!distance_x && !distance_y)
      return true;

    if (!scroll_event_sent_) {
      // Note that scroll start hints are in distance traveled, where
      // scroll deltas are in the opposite direction.
      GestureEventDetails scroll_details(ET_GESTURE_SCROLL_BEGIN, -distance_x,
                                         -distance_y);
      scroll_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);

      // Scroll focus point always starts with the first touch down point.
      scroll_focus_point_.SetPoint(e1.GetX(), e1.GetY());

      // Use the co-ordinates from the touch down, as these co-ordinates are
      // used to determine which layer the scroll should affect.
      Send(CreateGesture(scroll_details, e2.GetPointerId(), e2.GetToolType(),
                         e2.GetEventTime(), e1.GetX(), e1.GetY(), e1.GetRawX(),
                         e1.GetRawY(), e2.GetPointerCount(),
                         GetBoundingBox(e2, scroll_details.type()),
                         e2.GetFlags()));
      DCHECK(scroll_event_sent_);
    }
    scroll_focus_point_.SetPoint(scroll_focus_point_.x() - raw_distance_x,
                                 scroll_focus_point_.y() - raw_distance_y);

    GestureEventDetails scroll_details(ET_GESTURE_SCROLL_UPDATE, -distance_x,
                                       -distance_y);
    scroll_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
    const gfx::RectF bounding_box = GetBoundingBox(e2, scroll_details.type());
    const gfx::PointF raw_center =
        scroll_focus_point_ +
        gfx::Vector2dF(e2.GetRawOffsetX(), e2.GetRawOffsetY());
    Send(CreateGesture(scroll_details, e2.GetPointerId(), e2.GetToolType(),
                       e2.GetEventTime(), scroll_focus_point_.x(),
                       scroll_focus_point_.y(), raw_center.x(), raw_center.y(),
                       e2.GetPointerCount(), bounding_box, e2.GetFlags()));

    return true;
  }

  bool OnFling(const MotionEvent& e1,
               const MotionEvent& e2,
               float velocity_x,
               float velocity_y) override {
    if (snap_scroll_controller_.IsSnappingScrolls()) {
      if (snap_scroll_controller_.IsSnapHorizontal()) {
        velocity_y = 0;
      } else {
        velocity_x = 0;
      }
    }

    if (!velocity_x && !velocity_y)
      return true;

    DCHECK(scroll_event_sent_);
    if (!scroll_event_sent_) {
      // The native side needs a ET_GESTURE_SCROLL_BEGIN before
      // ET_SCROLL_FLING_START to send the fling to the correct target.
      // The distance traveled in one second is a reasonable scroll start hint.
      GestureEventDetails scroll_details(
          ET_GESTURE_SCROLL_BEGIN, velocity_x, velocity_y);
      scroll_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
      Send(CreateGesture(scroll_details, e2));
    }

    GestureEventDetails fling_details(
        ET_SCROLL_FLING_START, velocity_x, velocity_y);
    fling_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
    Send(CreateGesture(fling_details, e2));
    return true;
  }

  bool OnSwipe(const MotionEvent& e1,
               const MotionEvent& e2,
               float velocity_x,
               float velocity_y) override {
    GestureEventDetails swipe_details(ET_GESTURE_SWIPE, velocity_x, velocity_y);
    swipe_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
    Send(CreateGesture(swipe_details, e2));
    return true;
  }

  bool OnTwoFingerTap(const MotionEvent& e1, const MotionEvent& e2) override {
    // The location of the two finger tap event should be the location of the
    // primary pointer.
    GestureEventDetails two_finger_tap_details(
        ET_GESTURE_TWO_FINGER_TAP, e1.GetTouchMajor(), e1.GetTouchMajor());
    two_finger_tap_details.set_device_type(
        GestureDeviceType::DEVICE_TOUCHSCREEN);
    Send(CreateGesture(two_finger_tap_details,
                       e2.GetPointerId(),
                       e2.GetToolType(),
                       e2.GetEventTime(),
                       e1.GetX(),
                       e1.GetY(),
                       e1.GetRawX(),
                       e1.GetRawY(),
                       e2.GetPointerCount(),
                       GetBoundingBox(e2, two_finger_tap_details.type()),
                       e2.GetFlags()));
    return true;
  }

  void OnTapCancel(const MotionEvent& e) override {
    Send(CreateGesture(ET_GESTURE_TAP_CANCEL, e));
  }

  void OnShowPress(const MotionEvent& e) override {
    GestureEventDetails show_press_details(ET_GESTURE_SHOW_PRESS);
    show_press_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
    show_press_event_sent_ = true;
    Send(CreateGesture(show_press_details, e));
  }

  bool OnSingleTapUp(const MotionEvent& e, int tap_count) override {
    // This is a hack to address the issue where user hovers
    // over a link for longer than double_tap_timeout_, then
    // OnSingleTapConfirmed() is not triggered. But we still
    // want to trigger the tap event at UP. So we override
    // OnSingleTapUp() in this case. This assumes singleTapUp
    // gets always called before singleTapConfirmed.
    if (!ignore_single_tap_) {
      if (e.GetEventTime() - current_down_action_event_time_ >
          config_.gesture_detector_config.double_tap_timeout) {
        return OnSingleTapImpl(e, tap_count);
      } else if (!IsDoubleTapEnabled()) {
        // If double-tap has been disabled, there is no need to wait
        // for the double-tap timeout.
        return OnSingleTapImpl(e, tap_count);
      } else {
        // Notify Blink about this tapUp event anyway, when none of the above
        // conditions applied.
        Send(CreateTapGesture(ET_GESTURE_TAP_UNCONFIRMED, e, 1));
      }
    }

    if (e.GetAction() == MotionEvent::Action::UP &&
        !current_longpress_time_.is_null() &&
        !IsScaleGestureDetectionInProgress()) {
      GestureEventDetails long_tap_details(ET_GESTURE_LONG_TAP);
      long_tap_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
      Send(CreateGesture(long_tap_details, e));
      return true;
    }

    return false;
  }

  // DoubleTapListener implementation.
  bool OnSingleTapConfirmed(const MotionEvent& e) override {
    return OnSingleTapImpl(e, 1);
  }

  bool OnDoubleTap(const MotionEvent& e) override {
    return scale_gesture_detector_.OnDoubleTap(e);
  }

  bool OnDoubleTapEvent(const MotionEvent& e) override {
    switch (e.GetAction()) {
      case MotionEvent::Action::DOWN:
        gesture_detector_.set_longpress_enabled(false);
        break;

      case MotionEvent::Action::UP:
        if (!IsPinchInProgress() && !IsScrollInProgress()) {
          Send(CreateTapGesture(ET_GESTURE_DOUBLE_TAP, e, 1));
          return true;
        }
        break;

      default:
        break;
    }
    return false;
  }

  void OnLongPress(const MotionEvent& e) override {
    DCHECK(!IsDoubleTapInProgress());
    SetIgnoreSingleTap(true);
    GestureEventDetails long_press_details(ET_GESTURE_LONG_PRESS);
    long_press_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
    Send(CreateGesture(long_press_details, e));
  }

  GestureEventData CreateGesture(const GestureEventDetails& details,
                                 int motion_event_id,
                                 MotionEvent::ToolType primary_tool_type,
                                 base::TimeTicks time,
                                 float x,
                                 float y,
                                 float raw_x,
                                 float raw_y,
                                 size_t touch_point_count,
                                 const gfx::RectF& bounding_box,
                                 int flags) const {
    return GestureEventData(details,
                            motion_event_id,
                            primary_tool_type,
                            time,
                            x,
                            y,
                            raw_x,
                            raw_y,
                            touch_point_count,
                            bounding_box,
                            flags,
                            0U);
  }

  GestureEventData CreateGesture(EventType type,
                                 int motion_event_id,
                                 MotionEvent::ToolType primary_tool_type,
                                 base::TimeTicks time,
                                 float x,
                                 float y,
                                 float raw_x,
                                 float raw_y,
                                 size_t touch_point_count,
                                 const gfx::RectF& bounding_box,
                                 int flags) const {
    GestureEventDetails details(type);
    details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
    return GestureEventData(details,
                            motion_event_id,
                            primary_tool_type,
                            time,
                            x,
                            y,
                            raw_x,
                            raw_y,
                            touch_point_count,
                            bounding_box,
                            flags,
                            0U);
  }

  GestureEventData CreateGesture(const GestureEventDetails& details,
                                 const MotionEvent& event) const {
    return GestureEventData(details, event.GetPointerId(), event.GetToolType(),
                            event.GetEventTime(), event.GetX(), event.GetY(),
                            event.GetRawX(), event.GetRawY(),
                            event.GetPointerCount(),
                            GetBoundingBox(event, details.type()),
                            event.GetFlags(), event.GetUniqueEventId());
  }

  GestureEventData CreateGesture(EventType type,
                                 const MotionEvent& event) const {
    GestureEventDetails details(type);
    details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
    return CreateGesture(details, event);
  }

  GestureEventData CreateTapGesture(EventType type,
                                    const MotionEvent& event,
                                    int tap_count) const {
    DCHECK_GE(tap_count, 0);
    GestureEventDetails details(type);
    details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
    details.set_tap_count(tap_count);
    return CreateGesture(details, event);
  }

  gfx::RectF GetBoundingBox(const MotionEvent& event, EventType type) const {
    // Can't use gfx::RectF::Union, as it ignores touches with a radius of 0.
    float left = std::numeric_limits<float>::max();
    float top = std::numeric_limits<float>::max();
    float right = -std::numeric_limits<float>::max();
    float bottom = -std::numeric_limits<float>::max();
    for (size_t i = 0; i < event.GetPointerCount(); ++i) {
      float x, y, diameter;
      // Only for the show press and tap events, the bounding box is calculated
      // based on the touch start point and the maximum diameter before the
      // show press event is sent.
      if (type == ET_GESTURE_SHOW_PRESS || type == ET_GESTURE_TAP ||
          type == ET_GESTURE_TAP_UNCONFIRMED) {
        DCHECK_EQ(0U, i);
        diameter = max_diameter_before_show_press_;
        x = tap_down_point_.x();
        y = tap_down_point_.y();
      } else {
        diameter = event.GetTouchMajor(i);
        x = event.GetX(i);
        y = event.GetY(i);
      }
      x = x - diameter / 2;
      y = y - diameter / 2;
      left = std::min(left, x);
      right = std::max(right, x + diameter);
      top = std::min(top, y);
      bottom = std::max(bottom, y + diameter);
    }
    return gfx::RectF(left, top, right - left, bottom - top);
  }

  void SetDoubleTapEnabled(bool enabled) {
    DCHECK(!IsDoubleTapInProgress());
    gesture_detector_.SetDoubleTapListener(enabled ? this : NULL);
  }

  void SetMultiTouchZoomEnabled(bool enabled) {
    // Note that returning false from |OnScaleBegin()| or |OnScale()| prevents
    // the detector from emitting further scale updates for the current touch
    // sequence. Thus, if multitouch events are enabled in the middle of a
    // gesture, it will only take effect with the next gesture.
    ignore_multitouch_zoom_events_ = !enabled;
  }

  bool IsDoubleTapInProgress() const {
    return gesture_detector_.is_double_tapping() ||
           (IsScaleGestureDetectionInProgress() && InAnchoredScaleMode());
  }

  bool IsScrollInProgress() const { return scroll_event_sent_; }

  bool IsPinchInProgress() const { return pinch_event_sent_; }

 private:
  bool OnSingleTapImpl(const MotionEvent& e, int tap_count) {
    // Long taps in the edges of the screen have their events delayed by
    // ContentViewHolder for tab swipe operations. As a consequence of the delay
    // this method might be called after receiving the up event.
    // These corner cases should be ignored.
    if (ignore_single_tap_)
      return true;

    ignore_single_tap_ = true;

    Send(CreateTapGesture(ET_GESTURE_TAP, e, tap_count));
    return true;
  }

  bool IsScaleGestureDetectionInProgress() const {
    return scale_gesture_detector_.IsInProgress();
  }

  bool InAnchoredScaleMode() const {
    return scale_gesture_detector_.InAnchoredScaleMode();
  }

  bool IsDoubleTapEnabled() const {
    return gesture_detector_.has_doubletap_listener() &&
           client_->RequiresDoubleTapGestureEvents();
  }

  void SetIgnoreSingleTap(bool value) { ignore_single_tap_ = value; }

  gfx::Vector2dF SubtractSlopRegion(const float dx, const float dy) {
    float distance = std::sqrt(dx * dx + dy * dy);
    float epsilon = 1e-3f;
    if (distance > epsilon) {
      float ratio =
          std::max(0.f, distance - config_.gesture_detector_config.touch_slop) /
          distance;
      gfx::Vector2dF delta(dx * ratio, dy * ratio);
      return delta;
    }
    gfx::Vector2dF delta(dx, dy);
    return delta;
  }

  // When any of the currently down pointers exceeds its slop region
  // for the first time, scroll delta is adjusted.
  // The new deltas are calculated for each pointer individually,
  // and the final scroll delta is the average over all delta values.
  gfx::Vector2dF ComputeFirstScrollDelta(
      const MotionEvent& ev1,
      const MotionEvent& ev2,
      const MotionEvent& secondary_pointer_down) {
    // If there are more than two down pointers, tapping is not possible,
    // so Slop region is not deducted.
    DCHECK(ev2.GetPointerCount() < 3);

    gfx::Vector2dF delta(0, 0);
    for (size_t i = 0; i < ev2.GetPointerCount(); i++) {
      const int pointer_id = ev2.GetPointerId(i);
      const MotionEvent* source_pointer_down_event =
          gesture_detector_.GetSourcePointerDownEvent(
              ev1, &secondary_pointer_down, pointer_id);

      if (!source_pointer_down_event)
        continue;
      int source_index =
          source_pointer_down_event->FindPointerIndexOfId(pointer_id);
      DCHECK_GE(source_index, 0);
      if (source_index < 0)
        continue;
      float dx = source_pointer_down_event->GetX(source_index) - ev2.GetX(i);
      float dy = source_pointer_down_event->GetY(source_index) - ev2.GetY(i);
      delta += SubtractSlopRegion(dx, dy);
    }
    delta.Scale(1.0 / ev2.GetPointerCount());
    return delta;
  }

  const GestureProvider::Config config_;
  GestureProviderClient* const client_;

  GestureDetector gesture_detector_;
  ScaleGestureDetector scale_gesture_detector_;
  SnapScrollController snap_scroll_controller_;

  // Keeps track of the event time of the first down action in current touch
  // sequence.
  base::TimeTicks current_down_action_event_time_;

  // Keeps track of the current GESTURE_LONG_PRESS event. If a context menu is
  // opened after a GESTURE_LONG_PRESS, this is used to insert a
  // GESTURE_TAP_CANCEL for removing any ::active styling.
  base::TimeTicks current_longpress_time_;

  // Completely silence multi-touch (pinch) scaling events. Used in WebView when
  // zoom support is turned off.
  bool ignore_multitouch_zoom_events_;

  // TODO(klobag): This is to avoid a bug in GestureDetector. With multi-touch,
  // always_in_tap_region_ is not reset. So when the last finger is up,
  // |OnSingleTapUp()| will be mistakenly fired.
  bool ignore_single_tap_;

  // Tracks whether {PINCH|SCROLL}_BEGIN events have been forwarded for the
  // current touch sequence.
  bool pinch_event_sent_;
  bool scroll_event_sent_;

  // Only track the maximum diameter before the show press event has been
  // sent and a tap must still be possible for this touch sequence.
  float max_diameter_before_show_press_;

  gfx::PointF tap_down_point_;

  // Tracks whether an ET_GESTURE_SHOW_PRESS event has been sent for this touch
  // sequence.
  bool show_press_event_sent_;

  // The scroll focus point is set to the first touch down point when scroll
  // begins and is later updated based on the delta of touch points.
  gfx::PointF scroll_focus_point_;
  DISALLOW_COPY_AND_ASSIGN(GestureListenerImpl);
};

// GestureProvider

GestureProvider::GestureProvider(const Config& config,
                                 GestureProviderClient* client)
    : double_tap_support_for_page_(true),
      double_tap_support_for_platform_(
          config.double_tap_support_for_platform_enabled),
      gesture_begin_end_types_enabled_(config.gesture_begin_end_types_enabled) {
  DCHECK(client);
  DCHECK(!config.min_gesture_bounds_length ||
         !config.max_gesture_bounds_length ||
         config.min_gesture_bounds_length <= config.max_gesture_bounds_length);
  TRACE_EVENT0("input", "GestureProvider::InitGestureDetectors");
  gesture_listener_ = std::make_unique<GestureListenerImpl>(config, client);
  UpdateDoubleTapDetectionSupport();
}

GestureProvider::~GestureProvider() {
}

bool GestureProvider::OnTouchEvent(const MotionEvent& event) {
  TRACE_EVENT1("input",
               "GestureProvider::OnTouchEvent",
               "action",
               GetMotionEventActionName(event.GetAction()));
  DCHECK_NE(0u, event.GetPointerCount());

  if (!CanHandle(event))
    return false;

  OnTouchEventHandlingBegin(event);
  gesture_listener_->OnTouchEvent(event);
  OnTouchEventHandlingEnd(event);
  uma_histogram_.RecordTouchEvent(event);
  return true;
}

void GestureProvider::ResetDetection() {
  MotionEventGeneric generic_cancel_event(
      MotionEvent::Action::CANCEL, base::TimeTicks::Now(), PointerProperties());
  OnTouchEvent(generic_cancel_event);
}

void GestureProvider::SetMultiTouchZoomSupportEnabled(bool enabled) {
  gesture_listener_->SetMultiTouchZoomEnabled(enabled);
}

void GestureProvider::SetDoubleTapSupportForPlatformEnabled(bool enabled) {
  if (double_tap_support_for_platform_ == enabled)
    return;
  double_tap_support_for_platform_ = enabled;
  UpdateDoubleTapDetectionSupport();
}

void GestureProvider::SetDoubleTapSupportForPageEnabled(bool enabled) {
  if (double_tap_support_for_page_ == enabled)
    return;
  double_tap_support_for_page_ = enabled;
  UpdateDoubleTapDetectionSupport();
}

bool GestureProvider::IsScrollInProgress() const {
  return gesture_listener_->IsScrollInProgress();
}

bool GestureProvider::IsPinchInProgress() const {
  return gesture_listener_->IsPinchInProgress();
}

bool GestureProvider::IsDoubleTapInProgress() const {
  return gesture_listener_->IsDoubleTapInProgress();
}

bool GestureProvider::CanHandle(const MotionEvent& event) const {
  // Aura requires one cancel event per touch point, whereas Android requires
  // one cancel event per touch sequence. Thus we need to allow extra cancel
  // events.
  return current_down_event_ ||
         event.GetAction() == MotionEvent::Action::DOWN ||
         event.GetAction() == MotionEvent::Action::CANCEL;
}

void GestureProvider::OnTouchEventHandlingBegin(const MotionEvent& event) {
  switch (event.GetAction()) {
    case MotionEvent::Action::DOWN:
      current_down_event_ = event.Clone();
      if (gesture_begin_end_types_enabled_)
        gesture_listener_->Send(
            gesture_listener_->CreateGesture(ET_GESTURE_BEGIN, event));
      break;
    case MotionEvent::Action::POINTER_DOWN:
      if (gesture_begin_end_types_enabled_) {
        const int action_index = event.GetActionIndex();
        gesture_listener_->Send(gesture_listener_->CreateGesture(
            ET_GESTURE_BEGIN,
            event.GetPointerId(),
            event.GetToolType(),
            event.GetEventTime(),
            event.GetX(action_index),
            event.GetY(action_index),
            event.GetRawX(action_index),
            event.GetRawY(action_index),
            event.GetPointerCount(),
            gesture_listener_->GetBoundingBox(event, ET_GESTURE_BEGIN),
            event.GetFlags()));
      }
      break;
    case MotionEvent::Action::POINTER_UP:
    case MotionEvent::Action::UP:
    case MotionEvent::Action::CANCEL:
    case MotionEvent::Action::MOVE:
      break;
    case MotionEvent::Action::NONE:
    case MotionEvent::Action::HOVER_ENTER:
    case MotionEvent::Action::HOVER_EXIT:
    case MotionEvent::Action::HOVER_MOVE:
    case MotionEvent::Action::BUTTON_PRESS:
    case MotionEvent::Action::BUTTON_RELEASE:
      NOTREACHED();
      break;
  }
}

void GestureProvider::OnTouchEventHandlingEnd(const MotionEvent& event) {
  switch (event.GetAction()) {
    case MotionEvent::Action::UP:
    case MotionEvent::Action::CANCEL: {
      if (gesture_begin_end_types_enabled_)
        gesture_listener_->Send(
            gesture_listener_->CreateGesture(ET_GESTURE_END, event));

      if (event.GetAction() != MotionEvent::Action::CANCEL ||
          !GestureConfiguration::GetInstance()
               ->single_pointer_cancel_enabled() ||
          event.GetPointerCount() == 1)
        current_down_event_.reset();

      UpdateDoubleTapDetectionSupport();
      break;
    }
    case MotionEvent::Action::POINTER_UP:
      if (gesture_begin_end_types_enabled_)
        gesture_listener_->Send(
            gesture_listener_->CreateGesture(ET_GESTURE_END, event));
      break;
    case MotionEvent::Action::DOWN:
    case MotionEvent::Action::POINTER_DOWN:
    case MotionEvent::Action::MOVE:
      break;
    case MotionEvent::Action::NONE:
    case MotionEvent::Action::HOVER_ENTER:
    case MotionEvent::Action::HOVER_EXIT:
    case MotionEvent::Action::HOVER_MOVE:
    case MotionEvent::Action::BUTTON_PRESS:
    case MotionEvent::Action::BUTTON_RELEASE:
      NOTREACHED();
      break;
  }
}

void GestureProvider::UpdateDoubleTapDetectionSupport() {
  // The GestureDetector requires that any provided DoubleTapListener remain
  // attached to it for the duration of a touch sequence. Defer any potential
  // null'ing of the listener until the sequence has ended.
  if (current_down_event_)
    return;

  const bool double_tap_enabled =
      double_tap_support_for_page_ && double_tap_support_for_platform_;
  gesture_listener_->SetDoubleTapEnabled(double_tap_enabled);
}

}  //  namespace ui
