scale_gesture_detector.h revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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/memory/scoped_ptr.h"
9#include "base/time/time.h"
10#include "ui/events/gesture_detection/gesture_detection_export.h"
11#include "ui/events/gesture_detection/gesture_detector.h"
12
13namespace ui {
14
15class MotionEvent;
16
17// Port of ScaleGestureDetector.java from Android
18// * platform/frameworks/base/core/java/android/view/ScaleGestureDetector.java
19// * Change-Id: I3e7926a4f6f9ab4951f380bd004499c78b3bda69
20// * Please update the Change-Id as upstream Android changes are pulled.
21class ScaleGestureDetector : public GestureDetector::SimpleGestureListener {
22 public:
23  struct GESTURE_DETECTION_EXPORT Config {
24    Config();
25    ~Config();
26    GestureDetector::Config gesture_detector_config;
27
28    // Minimum accepted value for TouchMajor while scaling (in dips).
29    float min_scaling_touch_major;
30
31    // Minimum span needed to initiate a scaling gesture (in dips).
32    float min_scaling_span;
33
34    // Whether double-tap drag scaling is enabled.
35    bool quick_scale_enabled;
36
37    // Minimum pinch span change before pinch occurs (in dips). See
38    // crbug.com/373318.
39    float min_pinch_update_span_delta;
40  };
41
42  class ScaleGestureListener {
43   public:
44    virtual ~ScaleGestureListener() {}
45    virtual bool OnScale(const ScaleGestureDetector& detector,
46                         const MotionEvent& e) = 0;
47    virtual bool OnScaleBegin(const ScaleGestureDetector& detector,
48                              const MotionEvent& e) = 0;
49    virtual void OnScaleEnd(const ScaleGestureDetector& detector,
50                            const MotionEvent& e) = 0;
51  };
52
53  // A convenience class to extend when you only want to listen for a subset of
54  // scaling-related events. This implements all methods in
55  // |ScaleGestureListener| but does nothing.
56  // |OnScale()| returns false so that a subclass can retrieve the accumulated
57  // scale factor in an overridden |OnScaleEnd()|.
58  // |OnScaleBegin() returns true.
59  class SimpleScaleGestureListener : public ScaleGestureListener {
60   public:
61    // ScaleGestureListener implementation.
62    virtual bool OnScale(const ScaleGestureDetector&,
63                         const MotionEvent&) OVERRIDE;
64    virtual bool OnScaleBegin(const ScaleGestureDetector&,
65                              const MotionEvent&) OVERRIDE;
66    virtual void OnScaleEnd(const ScaleGestureDetector&,
67                            const MotionEvent&) OVERRIDE;
68  };
69
70  ScaleGestureDetector(const Config& config, ScaleGestureListener* listener);
71  virtual ~ScaleGestureDetector();
72
73  // Accepts MotionEvents and dispatches events to a |ScaleGestureListener|
74  // when appropriate.
75  //
76  // Note: Applications should pass a complete and consistent event stream to
77  // this method. A complete and consistent event stream involves all
78  // MotionEvents from the initial ACTION_DOWN to the final ACTION_UP or
79  // ACTION_CANCEL.
80  //
81  // Returns true if the event was processed and the detector wants to receive
82  // the rest of the MotionEvents in this event stream.
83  bool OnTouchEvent(const MotionEvent& event);
84
85  // Set whether the associated |ScaleGestureListener| should receive
86  // OnScale callbacks when the user performs a doubletap followed by a swipe.
87  void SetQuickScaleEnabled(bool scales);
88  bool IsQuickScaleEnabled() const;
89  bool IsInProgress() const;
90  bool InDoubleTapMode() const;
91  float GetFocusX() const;
92  float GetFocusY() const;
93  float GetCurrentSpan() const;
94  float GetCurrentSpanX() const;
95  float GetCurrentSpanY() const;
96  float GetPreviousSpan() const;
97  float GetPreviousSpanX() const;
98  float GetPreviousSpanY() const;
99  float GetScaleFactor() const;
100  base::TimeDelta GetTimeDelta() const;
101  base::TimeTicks GetEventTime() const;
102
103 private:
104  enum DoubleTapMode { DOUBLE_TAP_MODE_NONE, DOUBLE_TAP_MODE_IN_PROGRESS };
105
106  // DoubleTapListener implementation.
107  virtual bool OnDoubleTap(const MotionEvent& ev) OVERRIDE;
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  Config config_;
119
120  float focus_x_;
121  float focus_y_;
122
123  bool quick_scale_enabled_;
124
125  float curr_span_;
126  float prev_span_;
127  float initial_span_;
128  float curr_span_x_;
129  float curr_span_y_;
130  float prev_span_x_;
131  float prev_span_y_;
132  base::TimeTicks curr_time_;
133  base::TimeTicks prev_time_;
134  bool in_progress_;
135  float span_slop_;
136  float min_span_;
137
138  // Bounds for recently seen values.
139  float touch_upper_;
140  float touch_lower_;
141  float touch_history_last_accepted_;
142  int touch_history_direction_;
143  base::TimeTicks touch_history_last_accepted_time_;
144  float touch_min_major_;
145  float touch_max_major_;
146  float double_tap_focus_x_;
147  float double_tap_focus_y_;
148  DoubleTapMode double_tap_mode_;
149
150  bool event_before_or_above_starting_gesture_event_;
151
152  scoped_ptr<GestureDetector> gesture_detector_;
153
154  DISALLOW_COPY_AND_ASSIGN(ScaleGestureDetector);
155};
156
157}  // namespace ui
158
159#endif  // UI_EVENTS_GESTURE_DETECTION_SCALE_GESTURE_DETECTOR_H_
160