scale_gesture_detector.h revision 116680a4aac90f2aa7413d9095a592090648e557
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 to use touch major values when determining the scale span.
35    // Defaults to false.
36    bool use_touch_major_in_span;
37
38    // Whether double-tap drag scaling is enabled.
39    bool quick_scale_enabled;
40
41    // Minimum pinch span change before pinch occurs (in dips). See
42    // crbug.com/373318.
43    float min_pinch_update_span_delta;
44  };
45
46  class ScaleGestureListener {
47   public:
48    virtual ~ScaleGestureListener() {}
49    virtual bool OnScale(const ScaleGestureDetector& detector,
50                         const MotionEvent& e) = 0;
51    virtual bool OnScaleBegin(const ScaleGestureDetector& detector,
52                              const MotionEvent& e) = 0;
53    virtual void OnScaleEnd(const ScaleGestureDetector& detector,
54                            const MotionEvent& e) = 0;
55  };
56
57  // A convenience class to extend when you only want to listen for a subset of
58  // scaling-related events. This implements all methods in
59  // |ScaleGestureListener| but does nothing.
60  // |OnScale()| returns false so that a subclass can retrieve the accumulated
61  // scale factor in an overridden |OnScaleEnd()|.
62  // |OnScaleBegin() returns true.
63  class SimpleScaleGestureListener : public ScaleGestureListener {
64   public:
65    // ScaleGestureListener implementation.
66    virtual bool OnScale(const ScaleGestureDetector&,
67                         const MotionEvent&) OVERRIDE;
68    virtual bool OnScaleBegin(const ScaleGestureDetector&,
69                              const MotionEvent&) OVERRIDE;
70    virtual void OnScaleEnd(const ScaleGestureDetector&,
71                            const MotionEvent&) OVERRIDE;
72  };
73
74  ScaleGestureDetector(const Config& config, ScaleGestureListener* listener);
75  virtual ~ScaleGestureDetector();
76
77  // Accepts MotionEvents and dispatches events to a |ScaleGestureListener|
78  // when appropriate.
79  //
80  // Note: Applications should pass a complete and consistent event stream to
81  // this method. A complete and consistent event stream involves all
82  // MotionEvents from the initial ACTION_DOWN to the final ACTION_UP or
83  // ACTION_CANCEL.
84  //
85  // Returns true if the event was processed and the detector wants to receive
86  // the rest of the MotionEvents in this event stream.
87  bool OnTouchEvent(const MotionEvent& event);
88
89  // Set whether the associated |ScaleGestureListener| should receive
90  // OnScale callbacks when the user performs a doubletap followed by a swipe.
91  void SetQuickScaleEnabled(bool scales);
92  bool IsQuickScaleEnabled() const;
93  bool IsInProgress() const;
94  bool InDoubleTapMode() const;
95  float GetFocusX() const;
96  float GetFocusY() const;
97  float GetCurrentSpan() const;
98  float GetCurrentSpanX() const;
99  float GetCurrentSpanY() const;
100  float GetPreviousSpan() const;
101  float GetPreviousSpanX() const;
102  float GetPreviousSpanY() const;
103  float GetScaleFactor() const;
104  base::TimeDelta GetTimeDelta() const;
105  base::TimeTicks GetEventTime() const;
106
107 private:
108  enum DoubleTapMode { DOUBLE_TAP_MODE_NONE, DOUBLE_TAP_MODE_IN_PROGRESS };
109
110  // DoubleTapListener implementation.
111  virtual bool OnDoubleTap(const MotionEvent& ev) OVERRIDE;
112
113  // The TouchMajor/TouchMinor elements of a MotionEvent can flutter/jitter on
114  // some hardware/driver combos. Smooth out to get kinder, gentler behavior.
115  void AddTouchHistory(const MotionEvent& ev);
116  void ResetTouchHistory();
117
118  void ResetScaleWithSpan(float span);
119
120  ScaleGestureListener* const listener_;
121
122  Config config_;
123
124  float focus_x_;
125  float focus_y_;
126
127  bool quick_scale_enabled_;
128
129  float curr_span_;
130  float prev_span_;
131  float initial_span_;
132  float curr_span_x_;
133  float curr_span_y_;
134  float prev_span_x_;
135  float prev_span_y_;
136  base::TimeTicks curr_time_;
137  base::TimeTicks prev_time_;
138  bool in_progress_;
139  float span_slop_;
140  float min_span_;
141
142  // Bounds for recently seen values.
143  bool use_touch_major_in_span_;
144  float touch_upper_;
145  float touch_lower_;
146  float touch_history_last_accepted_;
147  int touch_history_direction_;
148  base::TimeTicks touch_history_last_accepted_time_;
149  float touch_min_major_;
150  float touch_max_major_;
151  float double_tap_focus_x_;
152  float double_tap_focus_y_;
153  DoubleTapMode double_tap_mode_;
154
155  bool event_before_or_above_starting_gesture_event_;
156
157  scoped_ptr<GestureDetector> gesture_detector_;
158
159  DISALLOW_COPY_AND_ASSIGN(ScaleGestureDetector);
160};
161
162}  // namespace ui
163
164#endif  // UI_EVENTS_GESTURE_DETECTION_SCALE_GESTURE_DETECTOR_H_
165