Home | History | Annotate | Download | only in gesture_detection
      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 
      5 #ifndef UI_EVENTS_GESTURE_DETECTION_SCALE_GESTURE_DETECTOR_H_
      6 #define UI_EVENTS_GESTURE_DETECTION_SCALE_GESTURE_DETECTOR_H_
      7 
      8 #include "base/time/time.h"
      9 #include "ui/events/gesture_detection/gesture_detection_export.h"
     10 
     11 namespace ui {
     12 
     13 class MotionEvent;
     14 
     15 // Port of ScaleGestureDetector.java from Android
     16 // * platform/frameworks/base/core/java/android/view/ScaleGestureDetector.java
     17 // * Change-Id: I3e7926a4f6f9ab4951f380bd004499c78b3bda69
     18 // * Please update the Change-Id as upstream Android changes are pulled.
     19 class ScaleGestureDetector {
     20  public:
     21   struct GESTURE_DETECTION_EXPORT Config {
     22     Config();
     23     ~Config();
     24 
     25     // Distance the current span can deviate from the initial span before
     26     // scaling will start (in dips). The span is the diameter of the circle with
     27     // a radius of average pointer deviation from the focal point.
     28     float span_slop;
     29 
     30     // Minimum accepted value for TouchMajor while scaling (in dips).
     31     float min_scaling_touch_major;
     32 
     33     // Minimum span needed to initiate a scaling gesture (in dips).
     34     float min_scaling_span;
     35 
     36     // Minimum pinch span change before pinch occurs (in dips). See
     37     // crbug.com/373318.
     38     float min_pinch_update_span_delta;
     39   };
     40 
     41   class ScaleGestureListener {
     42    public:
     43     virtual ~ScaleGestureListener() {}
     44     virtual bool OnScale(const ScaleGestureDetector& detector,
     45                          const MotionEvent& e) = 0;
     46     virtual bool OnScaleBegin(const ScaleGestureDetector& detector,
     47                               const MotionEvent& e) = 0;
     48     virtual void OnScaleEnd(const ScaleGestureDetector& detector,
     49                             const MotionEvent& e) = 0;
     50   };
     51 
     52   // A convenience class to extend when you only want to listen for a subset of
     53   // scaling-related events. This implements all methods in
     54   // |ScaleGestureListener| but does nothing.
     55   // |OnScale()| returns false so that a subclass can retrieve the accumulated
     56   // scale factor in an overridden |OnScaleEnd()|.
     57   // |OnScaleBegin() returns true.
     58   class SimpleScaleGestureListener : public ScaleGestureListener {
     59    public:
     60     // ScaleGestureListener implementation.
     61     virtual bool OnScale(const ScaleGestureDetector&,
     62                          const MotionEvent&) OVERRIDE;
     63     virtual bool OnScaleBegin(const ScaleGestureDetector&,
     64                               const MotionEvent&) OVERRIDE;
     65     virtual void OnScaleEnd(const ScaleGestureDetector&,
     66                             const MotionEvent&) OVERRIDE;
     67   };
     68 
     69   ScaleGestureDetector(const Config& config, ScaleGestureListener* listener);
     70   virtual ~ScaleGestureDetector();
     71 
     72   // Accepts MotionEvents and dispatches events to a |ScaleGestureListener|
     73   // when appropriate.
     74   //
     75   // Note: Applications should pass a complete and consistent event stream to
     76   // this method. A complete and consistent event stream involves all
     77   // MotionEvents from the initial ACTION_DOWN to the final ACTION_UP or
     78   // ACTION_CANCEL.
     79   //
     80   // Returns true if the event was processed and the detector wants to receive
     81   // the rest of the MotionEvents in this event stream.
     82   bool OnTouchEvent(const MotionEvent& event);
     83 
     84   // This method may be called by the owner when a a double-tap event has been
     85   // detected *for the same event stream* being fed to this instance of the
     86   // ScaleGestureDetector. As call order is important here, the double-tap
     87   // detector should always be offered events *before* the ScaleGestureDetector.
     88   bool OnDoubleTap(const MotionEvent& event);
     89 
     90   // Set whether the associated |ScaleGestureListener| should receive
     91   // OnScale callbacks when the user performs a doubletap followed by a swipe.
     92   bool IsInProgress() const;
     93   bool InDoubleTapMode() const;
     94   float GetFocusX() const;
     95   float GetFocusY() const;
     96   float GetCurrentSpan() const;
     97   float GetCurrentSpanX() const;
     98   float GetCurrentSpanY() const;
     99   float GetPreviousSpan() const;
    100   float GetPreviousSpanX() const;
    101   float GetPreviousSpanY() const;
    102   float GetScaleFactor() const;
    103   base::TimeDelta GetTimeDelta() const;
    104   base::TimeTicks GetEventTime() const;
    105 
    106  private:
    107   enum DoubleTapMode { DOUBLE_TAP_MODE_NONE, DOUBLE_TAP_MODE_IN_PROGRESS };
    108 
    109   // The TouchMajor/TouchMinor elements of a MotionEvent can flutter/jitter on
    110   // some hardware/driver combos. Smooth out to get kinder, gentler behavior.
    111   void AddTouchHistory(const MotionEvent& ev);
    112   void ResetTouchHistory();
    113 
    114   void ResetScaleWithSpan(float span);
    115 
    116   ScaleGestureListener* const listener_;
    117 
    118   float focus_x_;
    119   float focus_y_;
    120   float curr_span_;
    121   float prev_span_;
    122   float initial_span_;
    123   float curr_span_x_;
    124   float curr_span_y_;
    125   float prev_span_x_;
    126   float prev_span_y_;
    127   base::TimeTicks curr_time_;
    128   base::TimeTicks prev_time_;
    129   bool in_progress_;
    130   float span_slop_;
    131   float min_span_;
    132 
    133   // Bounds for recently seen values.
    134   float touch_upper_;
    135   float touch_lower_;
    136   float touch_history_last_accepted_;
    137   int touch_history_direction_;
    138   base::TimeTicks touch_history_last_accepted_time_;
    139   float touch_min_major_;
    140   float touch_max_major_;
    141   float double_tap_focus_x_;
    142   float double_tap_focus_y_;
    143   DoubleTapMode double_tap_mode_;
    144 
    145   bool event_before_or_above_starting_gesture_event_;
    146 
    147   DISALLOW_COPY_AND_ASSIGN(ScaleGestureDetector);
    148 };
    149 
    150 }  // namespace ui
    151 
    152 #endif  // UI_EVENTS_GESTURE_DETECTION_SCALE_GESTURE_DETECTOR_H_
    153