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

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

Issue 119323007: Add timestamps to synthesized events. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove target variables in pinch; fix computation of total duration. Created 6 years, 11 months 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 "base/logging.h" 9 #include "base/logging.h"
10 #include "content/common/input/input_event.h" 10 #include "content/common/input/input_event.h"
11 #include "ui/events/latency_info.h" 11 #include "ui/events/latency_info.h"
12 12
13 namespace content { 13 namespace content {
14 14
15 SyntheticPinchGesture::SyntheticPinchGesture( 15 SyntheticPinchGesture::SyntheticPinchGesture(
16 const SyntheticPinchGestureParams& params) 16 const SyntheticPinchGestureParams& params)
17 : params_(params), 17 : params_(params),
18 current_y_0_(0.0f), 18 start_y_0_(0.0f),
19 current_y_1_(0.0f), 19 start_y_1_(0.0f),
20 target_y_0_(0.0f),
21 target_y_1_(0.0f),
22 gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT), 20 gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT),
23 state_(SETUP) { 21 state_(SETUP) {
24 DCHECK_GE(params_.total_num_pixels_covered, 0); 22 DCHECK_GE(params_.total_num_pixels_covered, 0);
25 } 23 }
26 24
27 SyntheticPinchGesture::~SyntheticPinchGesture() {} 25 SyntheticPinchGesture::~SyntheticPinchGesture() {}
28 26
29 SyntheticGesture::Result SyntheticPinchGesture::ForwardInputEvents( 27 SyntheticGesture::Result SyntheticPinchGesture::ForwardInputEvents(
30 const base::TimeDelta& interval, SyntheticGestureTarget* target) { 28 const base::TimeTicks& timestamp, SyntheticGestureTarget* target) {
31 if (state_ == SETUP) { 29 if (state_ == SETUP) {
32 gesture_source_type_ = params_.gesture_source_type; 30 gesture_source_type_ = params_.gesture_source_type;
33 if (gesture_source_type_ == SyntheticGestureParams::DEFAULT_INPUT) 31 if (gesture_source_type_ == SyntheticGestureParams::DEFAULT_INPUT)
34 gesture_source_type_ = target->GetDefaultSyntheticGestureSourceType(); 32 gesture_source_type_ = target->GetDefaultSyntheticGestureSourceType();
35 33
36 if (!target->SupportsSyntheticGestureSourceType(gesture_source_type_)) 34 if (!target->SupportsSyntheticGestureSourceType(gesture_source_type_))
37 return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_SUPPORTED_BY_PLATFORM; 35 return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_SUPPORTED_BY_PLATFORM;
38 36
39 state_ = STARTED; 37 state_ = STARTED;
38 start_time_ = timestamp;
40 } 39 }
41 40
42 DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT); 41 DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT);
43 if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT) 42 if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT)
44 ForwardTouchInputEvents(interval, target); 43 ForwardTouchInputEvents(timestamp, target);
45 else 44 else
46 return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED; 45 return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED;
47 46
48 return (state_ == DONE) ? SyntheticGesture::GESTURE_FINISHED 47 return (state_ == DONE) ? SyntheticGesture::GESTURE_FINISHED
49 : SyntheticGesture::GESTURE_RUNNING; 48 : SyntheticGesture::GESTURE_RUNNING;
50 } 49 }
51 50
52 void SyntheticPinchGesture::ForwardTouchInputEvents( 51 void SyntheticPinchGesture::ForwardTouchInputEvents(
53 const base::TimeDelta& interval, SyntheticGestureTarget* target) { 52 const base::TimeTicks& timestamp, SyntheticGestureTarget* target) {
54 switch (state_) { 53 switch (state_) {
55 case STARTED: 54 case STARTED:
56 // Check for an early finish. 55 // Check for an early finish.
57 if (params_.total_num_pixels_covered == 0) { 56 if (params_.total_num_pixels_covered == 0) {
58 state_ = DONE; 57 state_ = DONE;
59 break; 58 break;
60 } 59 }
61 SetupCoordinates(target); 60 SetupCoordinatesAndStopTime(target);
62 PressTouchPoints(target); 61 PressTouchPoints(target, timestamp);
63 state_ = MOVING; 62 state_ = MOVING;
64 break; 63 break;
65 case MOVING: 64 case MOVING: {
66 UpdateTouchPoints(interval); 65 base::TimeTicks event_timestamp = ClampTimestamp(timestamp);
67 MoveTouchPoints(target); 66 float delta = GetDeltaForPointer0AtTime(event_timestamp);
68 if (HasReachedTarget()) { 67 MoveTouchPoints(target, delta, event_timestamp);
69 ReleaseTouchPoints(target); 68 if (HasReachedTarget(event_timestamp)) {
69 ReleaseTouchPoints(target, event_timestamp);
70 state_ = DONE; 70 state_ = DONE;
71 } 71 }
72 break; 72 } break;
73 case SETUP: 73 case SETUP:
74 NOTREACHED() << "State SETUP invalid for synthetic pinch."; 74 NOTREACHED() << "State SETUP invalid for synthetic pinch.";
75 case DONE: 75 case DONE:
76 NOTREACHED() << "State DONE invalid for synthetic pinch."; 76 NOTREACHED() << "State DONE invalid for synthetic pinch.";
77 } 77 }
78 } 78 }
79 79
80 void SyntheticPinchGesture::UpdateTouchPoints(base::TimeDelta interval) { 80 void SyntheticPinchGesture::PressTouchPoints(SyntheticGestureTarget* target,
81 // Compute the delta for the first pointer. The other one moves exactly 81 const base::TimeTicks& timestamp) {
82 // the same but in the opposite direction. 82 touch_event_.PressPoint(params_.anchor.x(), start_y_0_);
83 float delta = GetDeltaForPointer0(interval); 83 touch_event_.PressPoint(params_.anchor.x(), start_y_1_);
84 current_y_0_ += delta; 84 ForwardTouchEvent(target, timestamp);
85 current_y_1_ -= delta;
86 } 85 }
87 86
88 void SyntheticPinchGesture::PressTouchPoints(SyntheticGestureTarget* target) { 87 void SyntheticPinchGesture::MoveTouchPoints(SyntheticGestureTarget* target,
89 touch_event_.PressPoint(params_.anchor.x(), current_y_0_); 88 float delta,
90 touch_event_.PressPoint(params_.anchor.x(), current_y_1_); 89 const base::TimeTicks& timestamp) {
91 ForwardTouchEvent(target); 90 // The two pointers move in opposite directions.
92 } 91 float current_y_0 = start_y_0_ + delta;
92 float current_y_1 = start_y_1_ - delta;
93 93
94 void SyntheticPinchGesture::MoveTouchPoints(SyntheticGestureTarget* target) {
95 // The current pointer positions are stored as float but the pointer 94 // The current pointer positions are stored as float but the pointer
96 // coordinates of the input event are integers. Floor both positions so that 95 // coordinates of the input event are integers. Floor both positions so that
97 // in case of an odd distance one of the pointers (the one whose position goes 96 // in case of an odd distance one of the pointers (the one whose position goes
98 // down) moves one pixel further than the other. The explicit flooring is only 97 // down) moves one pixel further than the other. The explicit flooring is only
99 // needed for negative values. 98 // needed for negative values.
100 touch_event_.MovePoint(0, params_.anchor.x(), floor(current_y_0_)); 99 touch_event_.MovePoint(0, params_.anchor.x(), floor(current_y_0));
101 touch_event_.MovePoint(1, params_.anchor.x(), floor(current_y_1_)); 100 touch_event_.MovePoint(1, params_.anchor.x(), floor(current_y_1));
102 ForwardTouchEvent(target); 101 ForwardTouchEvent(target, timestamp);
103 } 102 }
104 103
105 void SyntheticPinchGesture::ReleaseTouchPoints(SyntheticGestureTarget* target) { 104 void SyntheticPinchGesture::ReleaseTouchPoints(
105 SyntheticGestureTarget* target, const base::TimeTicks& timestamp) {
106 touch_event_.ReleasePoint(0); 106 touch_event_.ReleasePoint(0);
107 touch_event_.ReleasePoint(1); 107 touch_event_.ReleasePoint(1);
108 ForwardTouchEvent(target); 108 ForwardTouchEvent(target, timestamp);
109 } 109 }
110 110
111 111 void SyntheticPinchGesture::ForwardTouchEvent(
112 void SyntheticPinchGesture::ForwardTouchEvent(SyntheticGestureTarget* target) 112 SyntheticGestureTarget* target, const base::TimeTicks& timestamp) {
113 const { 113 touch_event_.timeStampSeconds = ConvertTimestampToSeconds(timestamp);
114 target->DispatchInputEventToPlatform( 114 target->DispatchInputEventToPlatform(
115 InputEvent(touch_event_, ui::LatencyInfo(), false)); 115 InputEvent(touch_event_, ui::LatencyInfo(), false));
116 } 116 }
117 117
118 void SyntheticPinchGesture::SetupCoordinates(SyntheticGestureTarget* target) { 118 void SyntheticPinchGesture::SetupCoordinatesAndStopTime(
119 const float kTouchSlopInDips = target->GetTouchSlopInDips(); 119 SyntheticGestureTarget* target) {
120 const int kTouchSlopInDips = target->GetTouchSlopInDips();
121 params_.total_num_pixels_covered += 2 * kTouchSlopInDips;
120 float inner_distance_to_anchor = 2 * kTouchSlopInDips; 122 float inner_distance_to_anchor = 2 * kTouchSlopInDips;
121 float outer_distance_to_anchor = inner_distance_to_anchor + 123 float outer_distance_to_anchor =
122 params_.total_num_pixels_covered / 2.0f + 124 inner_distance_to_anchor + params_.total_num_pixels_covered / 2.0f;
123 kTouchSlopInDips;
124 125
125 // Move pointers away from each other to zoom in 126 // Move pointers away from each other to zoom in
126 // or towards each other to zoom out. 127 // or towards each other to zoom out.
127 if (params_.zoom_in) { 128 if (params_.zoom_in) {
128 current_y_0_ = params_.anchor.y() - inner_distance_to_anchor; 129 start_y_0_ = params_.anchor.y() - inner_distance_to_anchor;
129 current_y_1_ = params_.anchor.y() + inner_distance_to_anchor; 130 start_y_1_ = params_.anchor.y() + inner_distance_to_anchor;
130 target_y_0_ = params_.anchor.y() - outer_distance_to_anchor;
131 target_y_1_ = params_.anchor.y() + outer_distance_to_anchor;
132 } else { 131 } else {
133 current_y_0_ = params_.anchor.y() - outer_distance_to_anchor; 132 start_y_0_ = params_.anchor.y() - outer_distance_to_anchor;
134 current_y_1_ = params_.anchor.y() + outer_distance_to_anchor; 133 start_y_1_ = params_.anchor.y() + outer_distance_to_anchor;
135 target_y_0_ = params_.anchor.y() - inner_distance_to_anchor;
136 target_y_1_ = params_.anchor.y() + inner_distance_to_anchor;
137 } 134 }
135
136 int64 total_duration_in_us = static_cast<int64>(
137 1e6 * (static_cast<double>(params_.total_num_pixels_covered) /
138 params_.relative_pointer_speed_in_pixels_s));
139 DCHECK_GT(total_duration_in_us, 0);
140 stop_time_ =
141 start_time_ + base::TimeDelta::FromMicroseconds(total_duration_in_us);
138 } 142 }
139 143
140 float SyntheticPinchGesture::GetDeltaForPointer0( 144 float SyntheticPinchGesture::GetDeltaForPointer0AtTime(
141 const base::TimeDelta& interval) const { 145 const base::TimeTicks& timestamp) const {
142 float total_abs_delta = 146 float total_abs_delta;
143 params_.relative_pointer_speed_in_pixels_s * interval.InSecondsF();
144 147
145 // Make sure we're not moving too far in the final step. 148 // Make sure the final delta is correct. Using the computation below can lead
146 total_abs_delta = 149 // to issues with floating point precision.
147 std::min(total_abs_delta, ComputeAbsoluteRemainingDistance()); 150 if (HasReachedTarget(timestamp))
151 total_abs_delta = params_.total_num_pixels_covered;
152 else
153 total_abs_delta = params_.relative_pointer_speed_in_pixels_s *
154 (timestamp - start_time_).InSecondsF();
148 155
149 float abs_delta_pointer_0 = total_abs_delta / 2; 156 float abs_delta_pointer_0 = total_abs_delta / 2.0f;
150 return params_.zoom_in ? -abs_delta_pointer_0 : abs_delta_pointer_0; 157 return params_.zoom_in ? -abs_delta_pointer_0 : abs_delta_pointer_0;
151 } 158 }
152 159
153 float SyntheticPinchGesture::ComputeAbsoluteRemainingDistance() const { 160 base::TimeTicks SyntheticPinchGesture::ClampTimestamp(
154 float distance_0 = params_.zoom_in ? (current_y_0_ - target_y_0_) 161 const base::TimeTicks& timestamp) const {
155 : (target_y_0_ - current_y_0_); 162 return std::min(timestamp, stop_time_);
156 DCHECK_GE(distance_0, 0);
157
158 // Both pointers move the same overall distance at the same speed.
159 return 2 * distance_0;
160 } 163 }
161 164
162 bool SyntheticPinchGesture::HasReachedTarget() const { 165 bool SyntheticPinchGesture::HasReachedTarget(const base::TimeTicks& timestamp)
163 return ComputeAbsoluteRemainingDistance() == 0; 166 const {
167 return timestamp >= stop_time_;
164 } 168 }
165 169
166 } // namespace content 170 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698