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