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

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

Issue 2091213002: Decouple EventWithLatencyInfo and WebInputEventTraits [extern templates] (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Reference a better bug Created 4 years, 5 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/common/input/event_with_latency_info.h"
6
7 #include <bitset>
8 #include <limits>
9
10 #include "base/logging.h"
11
12 using blink::WebGestureEvent;
13 using blink::WebInputEvent;
14 using blink::WebKeyboardEvent;
15 using blink::WebMouseEvent;
16 using blink::WebMouseWheelEvent;
17 using blink::WebTouchEvent;
18 using std::numeric_limits;
19
20 namespace content {
21 namespace {
22
23 const int kInvalidTouchIndex = -1;
24
25 float GetUnacceleratedDelta(float accelerated_delta, float acceleration_ratio) {
26 return accelerated_delta * acceleration_ratio;
27 }
28
29 float GetAccelerationRatio(float accelerated_delta, float unaccelerated_delta) {
30 if (unaccelerated_delta == 0.f || accelerated_delta == 0.f)
31 return 1.f;
32 return unaccelerated_delta / accelerated_delta;
33 }
34
35 // Returns |kInvalidTouchIndex| iff |event| lacks a touch with an ID of |id|.
36 int GetIndexOfTouchID(const WebTouchEvent& event, int id) {
37 for (unsigned i = 0; i < event.touchesLength; ++i) {
38 if (event.touches[i].id == id)
39 return i;
40 }
41 return kInvalidTouchIndex;
42 }
43
44 WebInputEvent::DispatchType MergeDispatchTypes(
45 WebInputEvent::DispatchType type_1,
46 WebInputEvent::DispatchType type_2) {
47 static_assert(WebInputEvent::DispatchType::Blocking <
48 WebInputEvent::DispatchType::EventNonBlocking,
49 "Enum not ordered correctly");
50 static_assert(WebInputEvent::DispatchType::EventNonBlocking <
51 WebInputEvent::DispatchType::ListenersNonBlockingPassive,
52 "Enum not ordered correctly");
53 static_assert(
54 WebInputEvent::DispatchType::ListenersNonBlockingPassive <
55 WebInputEvent::DispatchType::ListenersForcedNonBlockingPassive,
56 "Enum not ordered correctly");
57 return static_cast<WebInputEvent::DispatchType>(
58 std::min(static_cast<int>(type_1), static_cast<int>(type_2)));
59 }
60
61 bool CanCoalesce(const blink::WebMouseEvent& event_to_coalesce,
62 const blink::WebMouseEvent& event) {
63 return event.type == event_to_coalesce.type &&
64 event.type == WebInputEvent::MouseMove;
65 }
66
67 void Coalesce(const WebMouseEvent& event_to_coalesce, WebMouseEvent* event) {
68 DCHECK(CanCoalesce(event_to_coalesce, *event));
69 // Accumulate movement deltas.
70 int x = event->movementX;
71 int y = event->movementY;
72 *event = event_to_coalesce;
73 event->movementX += x;
74 event->movementY += y;
75 }
76
77 bool CanCoalesce(const WebMouseWheelEvent& event_to_coalesce,
78 const WebMouseWheelEvent& event) {
79 return event.modifiers == event_to_coalesce.modifiers &&
80 event.scrollByPage == event_to_coalesce.scrollByPage &&
81 event.phase == event_to_coalesce.phase &&
82 event.momentumPhase == event_to_coalesce.momentumPhase &&
83 event.hasPreciseScrollingDeltas ==
84 event_to_coalesce.hasPreciseScrollingDeltas;
85 }
86
87 void Coalesce(const WebMouseWheelEvent& event_to_coalesce,
88 WebMouseWheelEvent* event) {
89 DCHECK(CanCoalesce(event_to_coalesce, *event));
90 float unaccelerated_x =
91 GetUnacceleratedDelta(event->deltaX, event->accelerationRatioX) +
92 GetUnacceleratedDelta(event_to_coalesce.deltaX,
93 event_to_coalesce.accelerationRatioX);
94 float unaccelerated_y =
95 GetUnacceleratedDelta(event->deltaY, event->accelerationRatioY) +
96 GetUnacceleratedDelta(event_to_coalesce.deltaY,
97 event_to_coalesce.accelerationRatioY);
98 event->deltaX += event_to_coalesce.deltaX;
99 event->deltaY += event_to_coalesce.deltaY;
100 event->wheelTicksX += event_to_coalesce.wheelTicksX;
101 event->wheelTicksY += event_to_coalesce.wheelTicksY;
102 event->accelerationRatioX =
103 GetAccelerationRatio(event->deltaX, unaccelerated_x);
104 event->accelerationRatioY =
105 GetAccelerationRatio(event->deltaY, unaccelerated_y);
106 }
107
108 bool CanCoalesce(const WebTouchEvent& event_to_coalesce,
109 const WebTouchEvent& event) {
110 if (event.type != event_to_coalesce.type ||
111 event.type != WebInputEvent::TouchMove ||
112 event.modifiers != event_to_coalesce.modifiers ||
113 event.touchesLength != event_to_coalesce.touchesLength ||
114 event.touchesLength > WebTouchEvent::touchesLengthCap)
115 return false;
116
117 static_assert(WebTouchEvent::touchesLengthCap <= sizeof(int32_t) * 8U,
118 "suboptimal touchesLengthCap size");
119 // Ensure that we have a 1-to-1 mapping of pointer ids between touches.
120 std::bitset<WebTouchEvent::touchesLengthCap> unmatched_event_touches(
121 (1 << event.touchesLength) - 1);
122 for (unsigned i = 0; i < event_to_coalesce.touchesLength; ++i) {
123 int event_touch_index =
124 GetIndexOfTouchID(event, event_to_coalesce.touches[i].id);
125 if (event_touch_index == kInvalidTouchIndex)
126 return false;
127 if (!unmatched_event_touches[event_touch_index])
128 return false;
129 unmatched_event_touches[event_touch_index] = false;
130 }
131 return unmatched_event_touches.none();
132 }
133
134 void Coalesce(const WebTouchEvent& event_to_coalesce, WebTouchEvent* event) {
135 DCHECK(CanCoalesce(event_to_coalesce, *event));
136 // The WebTouchPoints include absolute position information. So it is
137 // sufficient to simply replace the previous event with the new event->
138 // However, it is necessary to make sure that all the points have the
139 // correct state, i.e. the touch-points that moved in the last event, but
140 // didn't change in the current event, will have Stationary state. It is
141 // necessary to change them back to Moved state.
142 WebTouchEvent old_event = *event;
143 *event = event_to_coalesce;
144 for (unsigned i = 0; i < event->touchesLength; ++i) {
145 int i_old = GetIndexOfTouchID(old_event, event->touches[i].id);
146 if (old_event.touches[i_old].state == blink::WebTouchPoint::StateMoved)
147 event->touches[i].state = blink::WebTouchPoint::StateMoved;
148 }
149 event->movedBeyondSlopRegion |= old_event.movedBeyondSlopRegion;
150 event->dispatchType = MergeDispatchTypes(old_event.dispatchType,
151 event_to_coalesce.dispatchType);
152 }
153
154 bool CanCoalesce(const WebGestureEvent& event_to_coalesce,
155 const WebGestureEvent& event) {
156 if (event.type != event_to_coalesce.type ||
157 event.sourceDevice != event_to_coalesce.sourceDevice ||
158 event.modifiers != event_to_coalesce.modifiers)
159 return false;
160
161 if (event.type == WebInputEvent::GestureScrollUpdate)
162 return true;
163
164 // GesturePinchUpdate scales can be combined only if they share a focal point,
165 // e.g., with double-tap drag zoom.
166 if (event.type == WebInputEvent::GesturePinchUpdate &&
167 event.x == event_to_coalesce.x && event.y == event_to_coalesce.y)
168 return true;
169
170 return false;
171 }
172
173 void Coalesce(const WebGestureEvent& event_to_coalesce,
174 WebGestureEvent* event) {
175 DCHECK(CanCoalesce(event_to_coalesce, *event));
176 if (event->type == WebInputEvent::GestureScrollUpdate) {
177 event->data.scrollUpdate.deltaX +=
178 event_to_coalesce.data.scrollUpdate.deltaX;
179 event->data.scrollUpdate.deltaY +=
180 event_to_coalesce.data.scrollUpdate.deltaY;
181 DCHECK_EQ(
182 event->data.scrollUpdate.previousUpdateInSequencePrevented,
183 event_to_coalesce.data.scrollUpdate.previousUpdateInSequencePrevented);
184 } else if (event->type == WebInputEvent::GesturePinchUpdate) {
185 event->data.pinchUpdate.scale *= event_to_coalesce.data.pinchUpdate.scale;
186 // Ensure the scale remains bounded above 0 and below Infinity so that
187 // we can reliably perform operations like log on the values.
188 if (event->data.pinchUpdate.scale < numeric_limits<float>::min())
189 event->data.pinchUpdate.scale = numeric_limits<float>::min();
190 else if (event->data.pinchUpdate.scale > numeric_limits<float>::max())
191 event->data.pinchUpdate.scale = numeric_limits<float>::max();
192 }
193 }
194
195 } // namespace
196
197 template <class T>
198 bool EventWithLatencyInfo<T>::CanCoalesceWith(
199 const EventWithLatencyInfo& other) const {
200 if (other.event.type != event.type)
201 return false;
202
203 DCHECK_EQ(sizeof(T), event.size);
204 DCHECK_EQ(sizeof(T), other.event.size);
205
206 return CanCoalesce(other.event, event);
207 }
208
209 template <class T>
210 void EventWithLatencyInfo<T>::CoalesceWith(const EventWithLatencyInfo& other) {
211 // |other| should be a newer event than |this|.
212 if (other.latency.trace_id() >= 0 && latency.trace_id() >= 0)
213 DCHECK_GT(other.latency.trace_id(), latency.trace_id());
214
215 // New events get coalesced into older events, and the newer timestamp
216 // should always be preserved.
217 const double time_stamp_seconds = other.event.timeStampSeconds;
218 Coalesce(other.event, &event);
219 event.timeStampSeconds = time_stamp_seconds;
220
221 // When coalescing two input events, we keep the oldest LatencyInfo
222 // for Telemetry latency tests, since it will represent the longest
223 // latency.
224 other.latency = latency;
225 other.latency.set_coalesced();
226 }
227
228 // Explicit instantiations.
229 template class EXPORT_TEMPLATE_DEFINE(CONTENT_EXPORT)
230 EventWithLatencyInfo<blink::WebGestureEvent>;
231 template class EXPORT_TEMPLATE_DEFINE(CONTENT_EXPORT)
232 EventWithLatencyInfo<blink::WebMouseWheelEvent>;
233 template class EXPORT_TEMPLATE_DEFINE(CONTENT_EXPORT)
234 EventWithLatencyInfo<blink::WebMouseEvent>;
235 template class EXPORT_TEMPLATE_DEFINE(CONTENT_EXPORT)
236 EventWithLatencyInfo<blink::WebTouchEvent>;
237
238 } // namespace content
OLDNEW
« no previous file with comments | « content/common/input/event_with_latency_info.h ('k') | content/common/input/web_input_event_traits.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698