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

Side by Side Diff: content/common/input/event_with_latency_info.cc

Issue 2429953002: Implement compositor thread VSync aligned event queue (Closed)
Patch Set: dtapuska&enne's review: Call |Now()| once per loop; Chromium style; Remove parameterized test Created 4 years, 1 month 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
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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/common/input/event_with_latency_info.h" 5 #include "content/common/input/event_with_latency_info.h"
6 6
7 #include <bitset>
8 #include <limits>
9
10 using blink::WebGestureEvent;
11 using blink::WebInputEvent; 7 using blink::WebInputEvent;
12 using blink::WebKeyboardEvent;
13 using blink::WebMouseEvent;
14 using blink::WebMouseWheelEvent;
15 using blink::WebTouchEvent;
16 using std::numeric_limits;
17 8
18 namespace content { 9 namespace content {
19 namespace {
20
21 const int kInvalidTouchIndex = -1;
22
23 float GetUnacceleratedDelta(float accelerated_delta, float acceleration_ratio) {
24 return accelerated_delta * acceleration_ratio;
25 }
26
27 float GetAccelerationRatio(float accelerated_delta, float unaccelerated_delta) {
28 if (unaccelerated_delta == 0.f || accelerated_delta == 0.f)
29 return 1.f;
30 return unaccelerated_delta / accelerated_delta;
31 }
32
33 // Returns |kInvalidTouchIndex| iff |event| lacks a touch with an ID of |id|.
34 int GetIndexOfTouchID(const WebTouchEvent& event, int id) {
35 for (unsigned i = 0; i < event.touchesLength; ++i) {
36 if (event.touches[i].id == id)
37 return i;
38 }
39 return kInvalidTouchIndex;
40 }
41
42 WebInputEvent::DispatchType MergeDispatchTypes(
43 WebInputEvent::DispatchType type_1,
44 WebInputEvent::DispatchType type_2) {
45 static_assert(WebInputEvent::DispatchType::Blocking <
46 WebInputEvent::DispatchType::EventNonBlocking,
47 "Enum not ordered correctly");
48 static_assert(WebInputEvent::DispatchType::EventNonBlocking <
49 WebInputEvent::DispatchType::ListenersNonBlockingPassive,
50 "Enum not ordered correctly");
51 static_assert(
52 WebInputEvent::DispatchType::ListenersNonBlockingPassive <
53 WebInputEvent::DispatchType::ListenersForcedNonBlockingDueToFling,
54 "Enum not ordered correctly");
55 return static_cast<WebInputEvent::DispatchType>(
56 std::min(static_cast<int>(type_1), static_cast<int>(type_2)));
57 }
58
59 } // namespace
60
61 namespace internal {
62
63 bool CanCoalesce(const WebMouseEvent& event_to_coalesce,
64 const WebMouseEvent& event) {
65 return event.type == event_to_coalesce.type &&
66 event.type == WebInputEvent::MouseMove;
67 }
68
69 void Coalesce(const WebMouseEvent& event_to_coalesce, WebMouseEvent* event) {
70 DCHECK(CanCoalesce(event_to_coalesce, *event));
71 // Accumulate movement deltas.
72 int x = event->movementX;
73 int y = event->movementY;
74 *event = event_to_coalesce;
75 event->movementX += x;
76 event->movementY += y;
77 }
78
79 bool CanCoalesce(const WebMouseWheelEvent& event_to_coalesce,
80 const WebMouseWheelEvent& event) {
81 return event.modifiers == event_to_coalesce.modifiers &&
82 event.scrollByPage == event_to_coalesce.scrollByPage &&
83 event.phase == event_to_coalesce.phase &&
84 event.momentumPhase == event_to_coalesce.momentumPhase &&
85 event.hasPreciseScrollingDeltas ==
86 event_to_coalesce.hasPreciseScrollingDeltas;
87 }
88
89 void Coalesce(const WebMouseWheelEvent& event_to_coalesce,
90 WebMouseWheelEvent* event) {
91 DCHECK(CanCoalesce(event_to_coalesce, *event));
92 float unaccelerated_x =
93 GetUnacceleratedDelta(event->deltaX, event->accelerationRatioX) +
94 GetUnacceleratedDelta(event_to_coalesce.deltaX,
95 event_to_coalesce.accelerationRatioX);
96 float unaccelerated_y =
97 GetUnacceleratedDelta(event->deltaY, event->accelerationRatioY) +
98 GetUnacceleratedDelta(event_to_coalesce.deltaY,
99 event_to_coalesce.accelerationRatioY);
100 float old_deltaX = event->deltaX;
101 float old_deltaY = event->deltaY;
102 float old_wheelTicksX = event->wheelTicksX;
103 float old_wheelTicksY = event->wheelTicksY;
104 float old_movementX = event->movementX;
105 float old_movementY = event->movementY;
106 *event = event_to_coalesce;
107 event->deltaX += old_deltaX;
108 event->deltaY += old_deltaY;
109 event->wheelTicksX += old_wheelTicksX;
110 event->wheelTicksY += old_wheelTicksY;
111 event->movementX += old_movementX;
112 event->movementY += old_movementY;
113 event->accelerationRatioX =
114 GetAccelerationRatio(event->deltaX, unaccelerated_x);
115 event->accelerationRatioY =
116 GetAccelerationRatio(event->deltaY, unaccelerated_y);
117 }
118
119 bool CanCoalesce(const WebTouchEvent& event_to_coalesce,
120 const WebTouchEvent& event) {
121 if (event.type != event_to_coalesce.type ||
122 event.type != WebInputEvent::TouchMove ||
123 event.modifiers != event_to_coalesce.modifiers ||
124 event.touchesLength != event_to_coalesce.touchesLength ||
125 event.touchesLength > WebTouchEvent::kTouchesLengthCap)
126 return false;
127
128 static_assert(WebTouchEvent::kTouchesLengthCap <= sizeof(int32_t) * 8U,
129 "suboptimal kTouchesLengthCap size");
130 // Ensure that we have a 1-to-1 mapping of pointer ids between touches.
131 std::bitset<WebTouchEvent::kTouchesLengthCap> unmatched_event_touches(
132 (1 << event.touchesLength) - 1);
133 for (unsigned i = 0; i < event_to_coalesce.touchesLength; ++i) {
134 int event_touch_index =
135 GetIndexOfTouchID(event, event_to_coalesce.touches[i].id);
136 if (event_touch_index == kInvalidTouchIndex)
137 return false;
138 if (!unmatched_event_touches[event_touch_index])
139 return false;
140 unmatched_event_touches[event_touch_index] = false;
141 }
142 return unmatched_event_touches.none();
143 }
144
145 void Coalesce(const WebTouchEvent& event_to_coalesce, WebTouchEvent* event) {
146 DCHECK(CanCoalesce(event_to_coalesce, *event));
147 // The WebTouchPoints include absolute position information. So it is
148 // sufficient to simply replace the previous event with the new event->
149 // However, it is necessary to make sure that all the points have the
150 // correct state, i.e. the touch-points that moved in the last event, but
151 // didn't change in the current event, will have Stationary state. It is
152 // necessary to change them back to Moved state.
153 WebTouchEvent old_event = *event;
154 *event = event_to_coalesce;
155 for (unsigned i = 0; i < event->touchesLength; ++i) {
156 int i_old = GetIndexOfTouchID(old_event, event->touches[i].id);
157 if (old_event.touches[i_old].state == blink::WebTouchPoint::StateMoved)
158 event->touches[i].state = blink::WebTouchPoint::StateMoved;
159 }
160 event->movedBeyondSlopRegion |= old_event.movedBeyondSlopRegion;
161 event->dispatchType = MergeDispatchTypes(old_event.dispatchType,
162 event_to_coalesce.dispatchType);
163 }
164
165 bool CanCoalesce(const WebGestureEvent& event_to_coalesce,
166 const WebGestureEvent& event) {
167 if (event.type != event_to_coalesce.type ||
168 event.sourceDevice != event_to_coalesce.sourceDevice ||
169 event.modifiers != event_to_coalesce.modifiers)
170 return false;
171
172 if (event.type == WebInputEvent::GestureScrollUpdate)
173 return true;
174
175 // GesturePinchUpdate scales can be combined only if they share a focal point,
176 // e.g., with double-tap drag zoom.
177 if (event.type == WebInputEvent::GesturePinchUpdate &&
178 event.x == event_to_coalesce.x && event.y == event_to_coalesce.y)
179 return true;
180
181 return false;
182 }
183
184 void Coalesce(const WebGestureEvent& event_to_coalesce,
185 WebGestureEvent* event) {
186 DCHECK(CanCoalesce(event_to_coalesce, *event));
187 if (event->type == WebInputEvent::GestureScrollUpdate) {
188 event->data.scrollUpdate.deltaX +=
189 event_to_coalesce.data.scrollUpdate.deltaX;
190 event->data.scrollUpdate.deltaY +=
191 event_to_coalesce.data.scrollUpdate.deltaY;
192 DCHECK_EQ(
193 event->data.scrollUpdate.previousUpdateInSequencePrevented,
194 event_to_coalesce.data.scrollUpdate.previousUpdateInSequencePrevented);
195 } else if (event->type == WebInputEvent::GesturePinchUpdate) {
196 event->data.pinchUpdate.scale *= event_to_coalesce.data.pinchUpdate.scale;
197 // Ensure the scale remains bounded above 0 and below Infinity so that
198 // we can reliably perform operations like log on the values.
199 if (event->data.pinchUpdate.scale < numeric_limits<float>::min())
200 event->data.pinchUpdate.scale = numeric_limits<float>::min();
201 else if (event->data.pinchUpdate.scale > numeric_limits<float>::max())
202 event->data.pinchUpdate.scale = numeric_limits<float>::max();
203 }
204 }
205
206 bool CanCoalesce(const blink::WebInputEvent& event_to_coalesce,
207 const blink::WebInputEvent& event) {
208 if (blink::WebInputEvent::isGestureEventType(event_to_coalesce.type) &&
209 blink::WebInputEvent::isGestureEventType(event.type)) {
210 return CanCoalesce(
211 static_cast<const blink::WebGestureEvent&>(event_to_coalesce),
212 static_cast<const blink::WebGestureEvent&>(event));
213 }
214 if (blink::WebInputEvent::isMouseEventType(event_to_coalesce.type) &&
215 blink::WebInputEvent::isMouseEventType(event.type)) {
216 return CanCoalesce(
217 static_cast<const blink::WebMouseEvent&>(event_to_coalesce),
218 static_cast<const blink::WebMouseEvent&>(event));
219 }
220 if (blink::WebInputEvent::isTouchEventType(event_to_coalesce.type) &&
221 blink::WebInputEvent::isTouchEventType(event.type)) {
222 return CanCoalesce(
223 static_cast<const blink::WebTouchEvent&>(event_to_coalesce),
224 static_cast<const blink::WebTouchEvent&>(event));
225 }
226 if (event_to_coalesce.type == blink::WebInputEvent::MouseWheel &&
227 event.type == blink::WebInputEvent::MouseWheel) {
228 return CanCoalesce(
229 static_cast<const blink::WebMouseWheelEvent&>(event_to_coalesce),
230 static_cast<const blink::WebMouseWheelEvent&>(event));
231 }
232 return false;
233 }
234
235 void Coalesce(const blink::WebInputEvent& event_to_coalesce,
236 blink::WebInputEvent* event) {
237 if (blink::WebInputEvent::isGestureEventType(event_to_coalesce.type) &&
238 blink::WebInputEvent::isGestureEventType(event->type)) {
239 Coalesce(static_cast<const blink::WebGestureEvent&>(event_to_coalesce),
240 static_cast<blink::WebGestureEvent*>(event));
241 return;
242 }
243 if (blink::WebInputEvent::isMouseEventType(event_to_coalesce.type) &&
244 blink::WebInputEvent::isMouseEventType(event->type)) {
245 Coalesce(static_cast<const blink::WebMouseEvent&>(event_to_coalesce),
246 static_cast<blink::WebMouseEvent*>(event));
247 return;
248 }
249 if (blink::WebInputEvent::isTouchEventType(event_to_coalesce.type) &&
250 blink::WebInputEvent::isTouchEventType(event->type)) {
251 Coalesce(static_cast<const blink::WebTouchEvent&>(event_to_coalesce),
252 static_cast<blink::WebTouchEvent*>(event));
253 return;
254 }
255 if (event_to_coalesce.type == blink::WebInputEvent::MouseWheel &&
256 event->type == blink::WebInputEvent::MouseWheel) {
257 Coalesce(static_cast<const blink::WebMouseWheelEvent&>(event_to_coalesce),
258 static_cast<blink::WebMouseWheelEvent*>(event));
259 }
260 }
261
262 } // namespace internal
263 10
264 ScopedWebInputEventWithLatencyInfo::ScopedWebInputEventWithLatencyInfo( 11 ScopedWebInputEventWithLatencyInfo::ScopedWebInputEventWithLatencyInfo(
265 ui::ScopedWebInputEvent event, 12 ui::ScopedWebInputEvent event,
266 const ui::LatencyInfo& latency_info) 13 const ui::LatencyInfo& latency_info)
267 : event_(std::move(event)), latency_(latency_info) { 14 : event_(std::move(event)), latency_(latency_info) {
268 } 15 }
269 16
270 ScopedWebInputEventWithLatencyInfo::~ScopedWebInputEventWithLatencyInfo() {} 17 ScopedWebInputEventWithLatencyInfo::~ScopedWebInputEventWithLatencyInfo() {}
271 18
272 bool ScopedWebInputEventWithLatencyInfo::CanCoalesceWith( 19 bool ScopedWebInputEventWithLatencyInfo::CanCoalesceWith(
273 const ScopedWebInputEventWithLatencyInfo& other) const { 20 const ScopedWebInputEventWithLatencyInfo& other) const {
274 return internal::CanCoalesce(other.event(), event()); 21 return ui::CanCoalesce(other.event(), event());
275 } 22 }
276 23
277 void ScopedWebInputEventWithLatencyInfo::CoalesceWith( 24 void ScopedWebInputEventWithLatencyInfo::CoalesceWith(
278 const ScopedWebInputEventWithLatencyInfo& other) { 25 const ScopedWebInputEventWithLatencyInfo& other) {
279 // |other| should be a newer event than |this|. 26 // |other| should be a newer event than |this|.
280 if (other.latency_.trace_id() >= 0 && latency_.trace_id() >= 0) 27 if (other.latency_.trace_id() >= 0 && latency_.trace_id() >= 0)
281 DCHECK_GT(other.latency_.trace_id(), latency_.trace_id()); 28 DCHECK_GT(other.latency_.trace_id(), latency_.trace_id());
282 29
283 // New events get coalesced into older events, and the newer timestamp 30 // New events get coalesced into older events, and the newer timestamp
284 // should always be preserved. 31 // should always be preserved.
285 const double time_stamp_seconds = other.event().timeStampSeconds; 32 const double time_stamp_seconds = other.event().timeStampSeconds;
286 internal::Coalesce(other.event(), event_.get()); 33 ui::Coalesce(other.event(), event_.get());
287 event_->timeStampSeconds = time_stamp_seconds; 34 event_->timeStampSeconds = time_stamp_seconds;
288 35
289 // When coalescing two input events, we keep the oldest LatencyInfo 36 // When coalescing two input events, we keep the oldest LatencyInfo
290 // since it will represent the longest latency. 37 // since it will represent the longest latency.
291 other.latency_ = latency_; 38 other.latency_ = latency_;
292 other.latency_.set_coalesced(); 39 other.latency_.set_coalesced();
293 } 40 }
294 41
295 const blink::WebInputEvent& ScopedWebInputEventWithLatencyInfo::event() const { 42 const blink::WebInputEvent& ScopedWebInputEventWithLatencyInfo::event() const {
296 return *event_; 43 return *event_;
297 } 44 }
298 45
299 blink::WebInputEvent& ScopedWebInputEventWithLatencyInfo::event() { 46 blink::WebInputEvent& ScopedWebInputEventWithLatencyInfo::event() {
300 return *event_; 47 return *event_;
301 } 48 }
302 49
303 } // namespace content 50 } // namespace content
OLDNEW
« no previous file with comments | « content/common/input/event_with_latency_info.h ('k') | content/renderer/input/main_thread_event_queue_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698