Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(380)

Side by Side Diff: content/browser/renderer_host/input/synthetic_pinch_gesture.cc

Issue 95153002: Make touch-based synthetic gesture take touch slop into account. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Minor refactoring of pinch gesture. Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/renderer_host/input/synthetic_pinch_gesture.h" 5 #include "content/browser/renderer_host/input/synthetic_pinch_gesture.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 8
9 #include "content/common/input/input_event.h" 9 #include "content/common/input/input_event.h"
10 #include "ui/events/latency_info.h" 10 #include "ui/events/latency_info.h"
11 11
12 namespace content { 12 namespace content {
13 namespace {
14
15 // TODO(dominikg): Use touch slop to compute this value.
16 const float kMinPointerDistance = 40.0f;
17
18 }
19 13
20 SyntheticPinchGesture::SyntheticPinchGesture( 14 SyntheticPinchGesture::SyntheticPinchGesture(
21 const SyntheticPinchGestureParams& params) 15 const SyntheticPinchGestureParams& params)
22 : params_(params), started_(false) { 16 : params_(params),
17 current_y_0_(0),
18 current_y_1_(0),
19 target_y_0_(0),
20 target_y_1_(0),
21 gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT),
22 state_(SETUP) {
23 DCHECK_GE(params_.total_num_pixels_covered, 0); 23 DCHECK_GE(params_.total_num_pixels_covered, 0);
24 }
24 25
25 float inner_distance_to_anchor = kMinPointerDistance / 2.0f; 26 SyntheticPinchGesture::~SyntheticPinchGesture() {}
26 float outer_distance_to_anchor = 27
27 inner_distance_to_anchor + params_.total_num_pixels_covered / 2.0f; 28 SyntheticGesture::Result SyntheticPinchGesture::ForwardInputEvents(
29 const base::TimeDelta& interval, SyntheticGestureTarget* target) {
30 if (state_ == SETUP) {
31 gesture_source_type_ = params_.gesture_source_type;
32 if (gesture_source_type_ == SyntheticGestureParams::DEFAULT_INPUT)
33 gesture_source_type_ = target->GetDefaultSyntheticGestureSourceType();
34
35 if (!target->SupportsSyntheticGestureSourceType(gesture_source_type_))
36 return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_SUPPORTED_BY_PLATFORM;
37
38 SetupCoordinates(target);
39
40 state_ = STARTED;
41 }
42
43 DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT);
44 if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT)
45 ForwardTouchInputEvents(interval, target);
46 else
47 return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED;
48
49 return (state_ == DONE) ? SyntheticGesture::GESTURE_FINISHED
50 : SyntheticGesture::GESTURE_RUNNING;
51 }
52
53 void SyntheticPinchGesture::ForwardTouchInputEvents(
54 const base::TimeDelta& interval, SyntheticGestureTarget* target) {
55 switch (state_) {
56 case STARTED:
57 // Check for an early finish.
58 if (HasReachedTarget()) {
59 state_ = DONE;
60 break;
61 }
62 PressTouchPoints(target);
63 state_ = MOVING;
64 break;
65 case MOVING:
66 UpdateTouchPoints(interval);
67 MoveTouchPoints(target);
68 if (HasReachedTarget()) {
69 ReleaseTouchPoints(target);
70 state_ = DONE;
71 }
72 break;
73 case SETUP:
74 NOTREACHED()
75 << "State SETUP invalid for synthetic pinch.";
76 case DONE:
77 NOTREACHED()
78 << "State DONE invalid for synthetic pinch.";
79 }
80 }
81
82 void SyntheticPinchGesture::UpdateTouchPoints(base::TimeDelta interval) {
83 // Compute the delta for the first pointer. The other one moves exactly
84 // the same but in the opposite direction.
85 const float delta = GetDeltaForPointer0(interval);
86 current_y_0_ += delta;
87 current_y_1_ -= delta;
88 }
89
90 void SyntheticPinchGesture::PressTouchPoints(SyntheticGestureTarget* target) {
91 touch_event_.PressPoint(params_.anchor.x(), current_y_0_);
92 touch_event_.PressPoint(params_.anchor.x(), current_y_1_);
93 ForwardTouchEvent(target);
94 }
95
96 void SyntheticPinchGesture::MoveTouchPoints(SyntheticGestureTarget* target) {
97 // The current pointer positions are stored as float but the pointer
98 // coordinates of the input event are integers. Floor both positions so
99 // that in case of an odd distance one of the pointers (the one whose
100 // position goes down) moves one pixel further than the other. The
101 // explicit flooring is only needed for negative values.
102 touch_event_.MovePoint(0, params_.anchor.x(), floor(current_y_0_));
103 touch_event_.MovePoint(1, params_.anchor.x(), floor(current_y_1_));
104 ForwardTouchEvent(target);
105 }
106
107 void SyntheticPinchGesture::ReleaseTouchPoints(SyntheticGestureTarget* target) {
108 touch_event_.ReleasePoint(0);
109 touch_event_.ReleasePoint(1);
110 ForwardTouchEvent(target);
111 }
112
113 void SyntheticPinchGesture::ForwardTouchEvent(SyntheticGestureTarget* target)
114 const {
115 target->DispatchInputEventToPlatform(
116 InputEvent(touch_event_, ui::LatencyInfo(), false));
117 }
118
119 void SyntheticPinchGesture::SetupCoordinates(SyntheticGestureTarget* target) {
120 DCHECK_EQ(state_, SETUP);
121
122 float inner_distance_to_anchor = 2 * target->GetTouchSlopInDips();
123 float outer_distance_to_anchor = inner_distance_to_anchor +
124 params_.total_num_pixels_covered / 2.0f +
125 target->GetTouchSlopInDips();
28 126
29 // Move pointers away from each other to zoom in 127 // Move pointers away from each other to zoom in
30 // or towards each other to zoom out. 128 // or towards each other to zoom out.
31 if (params_.zoom_in) { 129 if (params_.zoom_in) {
32 current_y_0_ = params_.anchor.y() - inner_distance_to_anchor; 130 current_y_0_ = params_.anchor.y() - inner_distance_to_anchor;
33 current_y_1_ = params_.anchor.y() + inner_distance_to_anchor; 131 current_y_1_ = params_.anchor.y() + inner_distance_to_anchor;
34 target_y_0_ = params_.anchor.y() - outer_distance_to_anchor; 132 target_y_0_ = params_.anchor.y() - outer_distance_to_anchor;
35 target_y_1_ = params_.anchor.y() + outer_distance_to_anchor; 133 target_y_1_ = params_.anchor.y() + outer_distance_to_anchor;
36 } else { 134 } else {
37 current_y_0_ = params_.anchor.y() - outer_distance_to_anchor; 135 current_y_0_ = params_.anchor.y() - outer_distance_to_anchor;
38 current_y_1_ = params_.anchor.y() + outer_distance_to_anchor; 136 current_y_1_ = params_.anchor.y() + outer_distance_to_anchor;
39 target_y_0_ = params_.anchor.y() - inner_distance_to_anchor; 137 target_y_0_ = params_.anchor.y() - inner_distance_to_anchor;
40 target_y_1_ = params_.anchor.y() + inner_distance_to_anchor; 138 target_y_1_ = params_.anchor.y() + inner_distance_to_anchor;
41 } 139 }
42 } 140 }
43 141
44 SyntheticPinchGesture::~SyntheticPinchGesture() {}
45
46 SyntheticGesture::Result SyntheticPinchGesture::ForwardInputEvents(
47 const base::TimeDelta& interval, SyntheticGestureTarget* target) {
48
49 SyntheticGestureParams::GestureSourceType source =
50 params_.gesture_source_type;
51 if (source == SyntheticGestureParams::DEFAULT_INPUT)
52 source = target->GetDefaultSyntheticGestureSourceType();
53
54 if (!target->SupportsSyntheticGestureSourceType(source))
55 return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_SUPPORTED_BY_PLATFORM;
56
57 if (source == SyntheticGestureParams::TOUCH_INPUT)
58 return ForwardTouchInputEvents(interval, target);
59 else
60 return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED;
61 }
62
63 SyntheticGesture::Result SyntheticPinchGesture::ForwardTouchInputEvents(
64 const base::TimeDelta& interval, SyntheticGestureTarget* target) {
65 if (HasFinished())
66 return SyntheticGesture::GESTURE_FINISHED;
67
68 if (!started_) {
69 touch_event_.PressPoint(params_.anchor.x(), current_y_0_);
70 touch_event_.PressPoint(params_.anchor.x(), current_y_1_);
71 ForwardTouchEvent(target);
72 started_ = true;
73 }
74
75 // Compute the delta for the first pointer. The other one moves exactly
76 // the same but in the opposite direction.
77 float delta = GetDeltaForPointer0(interval);
78 current_y_0_ += delta;
79 current_y_1_ -= delta;
80 // The current pointer positions are stored as float but the pointer
81 // coordinates of the input event are integers. Floor both positions so that
82 // in case of an odd distance one of the pointers (the one whose position goes
83 // down) moves one pixel further than the other. The explicit flooring is only
84 // needed for negative values.
85 touch_event_.MovePoint(0, params_.anchor.x(), floor(current_y_0_));
86 touch_event_.MovePoint(1, params_.anchor.x(), floor(current_y_1_));
87 ForwardTouchEvent(target);
88
89 if (HasFinished()) {
90 touch_event_.ReleasePoint(0);
91 touch_event_.ReleasePoint(1);
92 ForwardTouchEvent(target);
93 return SyntheticGesture::GESTURE_FINISHED;
94 }
95
96 return SyntheticGesture::GESTURE_RUNNING;
97 }
98
99 void SyntheticPinchGesture::ForwardTouchEvent(SyntheticGestureTarget* target) {
100 target->DispatchInputEventToPlatform(
101 InputEvent(touch_event_, ui::LatencyInfo(), false));
102 }
103
104 float SyntheticPinchGesture::GetDeltaForPointer0( 142 float SyntheticPinchGesture::GetDeltaForPointer0(
105 const base::TimeDelta& interval) const { 143 const base::TimeDelta& interval) const {
106 float total_abs_delta = 144 float total_abs_delta =
107 params_.relative_pointer_speed_in_pixels_s * interval.InSecondsF(); 145 params_.relative_pointer_speed_in_pixels_s * interval.InSecondsF();
108 146
109 // Make sure we're not moving too far in the final step. 147 // Make sure we're not moving too far in the final step.
110 total_abs_delta = 148 total_abs_delta =
111 std::min(total_abs_delta, ComputeAbsoluteRemainingDistance()); 149 std::min(total_abs_delta, ComputeAbsoluteRemainingDistance());
112 150
113 float abs_delta_pointer_0 = total_abs_delta / 2; 151 float abs_delta_pointer_0 = total_abs_delta / 2;
114 return params_.zoom_in ? -abs_delta_pointer_0 : abs_delta_pointer_0; 152 return params_.zoom_in ? -abs_delta_pointer_0 : abs_delta_pointer_0;
115 } 153 }
116 154
117 float SyntheticPinchGesture::ComputeAbsoluteRemainingDistance() const { 155 float SyntheticPinchGesture::ComputeAbsoluteRemainingDistance() const {
118 float distance_0 = params_.zoom_in ? (current_y_0_ - target_y_0_) 156 float distance_0 = params_.zoom_in ? (current_y_0_ - target_y_0_)
119 : (target_y_0_ - current_y_0_); 157 : (target_y_0_ - current_y_0_);
120 DCHECK_GE(distance_0, 0); 158 DCHECK_GE(distance_0, 0);
121 159
122 // Both pointers move the same overall distance at the same speed. 160 // Both pointers move the same overall distance at the same speed.
123 return 2 * distance_0; 161 return 2 * distance_0;
124 } 162 }
125 163
126 bool SyntheticPinchGesture::HasFinished() const { 164 bool SyntheticPinchGesture::HasReachedTarget() const {
127 return ComputeAbsoluteRemainingDistance() == 0; 165 return ComputeAbsoluteRemainingDistance() == 0;
128 } 166 }
129 167
130 } // namespace content 168 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698