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

Side by Side Diff: content/common/input/web_input_event_traits.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
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/common/input/web_input_event_traits.h" 5 #include "content/common/input/web_input_event_traits.h"
6 6
7 #include <bitset>
8 #include <limits>
9
10 #include "base/logging.h" 7 #include "base/logging.h"
11 #include "base/strings/stringprintf.h" 8 #include "base/strings/stringprintf.h"
12 9
13 using base::StringAppendF; 10 using base::StringAppendF;
14 using base::SStringPrintf; 11 using base::SStringPrintf;
15 using blink::WebGestureEvent; 12 using blink::WebGestureEvent;
16 using blink::WebInputEvent; 13 using blink::WebInputEvent;
17 using blink::WebKeyboardEvent; 14 using blink::WebKeyboardEvent;
18 using blink::WebMouseEvent; 15 using blink::WebMouseEvent;
19 using blink::WebMouseWheelEvent; 16 using blink::WebMouseWheelEvent;
20 using blink::WebTouchEvent; 17 using blink::WebTouchEvent;
21 using blink::WebTouchPoint; 18 using blink::WebTouchPoint;
22 using std::numeric_limits;
23 19
24 namespace content { 20 namespace content {
25 namespace { 21 namespace {
26 22
27 const int kInvalidTouchIndex = -1;
28
29 void ApppendEventDetails(const WebKeyboardEvent& event, std::string* result) { 23 void ApppendEventDetails(const WebKeyboardEvent& event, std::string* result) {
30 StringAppendF(result, 24 StringAppendF(result,
31 "{\n WinCode: %d\n NativeCode: %d\n IsSystem: %d\n" 25 "{\n WinCode: %d\n NativeCode: %d\n IsSystem: %d\n"
32 " Text: %s\n UnmodifiedText: %s\n KeyIdentifier: %s\n}", 26 " Text: %s\n UnmodifiedText: %s\n KeyIdentifier: %s\n}",
33 event.windowsKeyCode, 27 event.windowsKeyCode,
34 event.nativeKeyCode, 28 event.nativeKeyCode,
35 event.isSystemKey, 29 event.isSystemKey,
36 reinterpret_cast<const char*>(event.text), 30 reinterpret_cast<const char*>(event.text),
37 reinterpret_cast<const char*>(event.unmodifiedText), 31 reinterpret_cast<const char*>(event.unmodifiedText),
38 reinterpret_cast<const char*>(event.keyIdentifier)); 32 reinterpret_cast<const char*>(event.keyIdentifier));
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 StringAppendF(result, 99 StringAppendF(result,
106 "{\n Touches: %u, DispatchType: %d, CausesScrolling: %d," 100 "{\n Touches: %u, DispatchType: %d, CausesScrolling: %d,"
107 " uniqueTouchEventId: %u\n[\n", 101 " uniqueTouchEventId: %u\n[\n",
108 event.touchesLength, event.dispatchType, 102 event.touchesLength, event.dispatchType,
109 event.movedBeyondSlopRegion, event.uniqueTouchEventId); 103 event.movedBeyondSlopRegion, event.uniqueTouchEventId);
110 for (unsigned i = 0; i < event.touchesLength; ++i) 104 for (unsigned i = 0; i < event.touchesLength; ++i)
111 ApppendTouchPointDetails(event.touches[i], result); 105 ApppendTouchPointDetails(event.touches[i], result);
112 result->append(" ]\n}"); 106 result->append(" ]\n}");
113 } 107 }
114 108
115 bool CanCoalesce(const WebKeyboardEvent& event_to_coalesce,
116 const WebKeyboardEvent& event) {
117 return false;
118 }
119
120 void Coalesce(const WebKeyboardEvent& event_to_coalesce,
121 WebKeyboardEvent* event) {
122 DCHECK(CanCoalesce(event_to_coalesce, *event));
123 }
124
125 bool CanCoalesce(const WebMouseEvent& event_to_coalesce,
126 const WebMouseEvent& event) {
127 return event.type == event_to_coalesce.type &&
128 event.type == WebInputEvent::MouseMove;
129 }
130
131 void Coalesce(const WebMouseEvent& event_to_coalesce, WebMouseEvent* event) {
132 DCHECK(CanCoalesce(event_to_coalesce, *event));
133 // Accumulate movement deltas.
134 int x = event->movementX;
135 int y = event->movementY;
136 *event = event_to_coalesce;
137 event->movementX += x;
138 event->movementY += y;
139 }
140
141 bool CanCoalesce(const WebMouseWheelEvent& event_to_coalesce,
142 const WebMouseWheelEvent& event) {
143 return event.modifiers == event_to_coalesce.modifiers &&
144 event.scrollByPage == event_to_coalesce.scrollByPage &&
145 event.phase == event_to_coalesce.phase &&
146 event.momentumPhase == event_to_coalesce.momentumPhase &&
147 event.hasPreciseScrollingDeltas ==
148 event_to_coalesce.hasPreciseScrollingDeltas;
149 }
150
151 float GetUnacceleratedDelta(float accelerated_delta, float acceleration_ratio) {
152 return accelerated_delta * acceleration_ratio;
153 }
154
155 float GetAccelerationRatio(float accelerated_delta, float unaccelerated_delta) {
156 if (unaccelerated_delta == 0.f || accelerated_delta == 0.f)
157 return 1.f;
158 return unaccelerated_delta / accelerated_delta;
159 }
160
161 void Coalesce(const WebMouseWheelEvent& event_to_coalesce,
162 WebMouseWheelEvent* event) {
163 DCHECK(CanCoalesce(event_to_coalesce, *event));
164 float unaccelerated_x =
165 GetUnacceleratedDelta(event->deltaX,
166 event->accelerationRatioX) +
167 GetUnacceleratedDelta(event_to_coalesce.deltaX,
168 event_to_coalesce.accelerationRatioX);
169 float unaccelerated_y =
170 GetUnacceleratedDelta(event->deltaY,
171 event->accelerationRatioY) +
172 GetUnacceleratedDelta(event_to_coalesce.deltaY,
173 event_to_coalesce.accelerationRatioY);
174 event->deltaX += event_to_coalesce.deltaX;
175 event->deltaY += event_to_coalesce.deltaY;
176 event->wheelTicksX += event_to_coalesce.wheelTicksX;
177 event->wheelTicksY += event_to_coalesce.wheelTicksY;
178 event->accelerationRatioX =
179 GetAccelerationRatio(event->deltaX, unaccelerated_x);
180 event->accelerationRatioY =
181 GetAccelerationRatio(event->deltaY, unaccelerated_y);
182 }
183
184 // Returns |kInvalidTouchIndex| iff |event| lacks a touch with an ID of |id|.
185 int GetIndexOfTouchID(const WebTouchEvent& event, int id) {
186 for (unsigned i = 0; i < event.touchesLength; ++i) {
187 if (event.touches[i].id == id)
188 return i;
189 }
190 return kInvalidTouchIndex;
191 }
192
193 WebInputEvent::DispatchType MergeDispatchTypes(
194 WebInputEvent::DispatchType type_1,
195 WebInputEvent::DispatchType type_2) {
196 static_assert(WebInputEvent::DispatchType::Blocking <
197 WebInputEvent::DispatchType::EventNonBlocking,
198 "Enum not ordered correctly");
199 static_assert(WebInputEvent::DispatchType::EventNonBlocking <
200 WebInputEvent::DispatchType::ListenersNonBlockingPassive,
201 "Enum not ordered correctly");
202 static_assert(
203 WebInputEvent::DispatchType::ListenersNonBlockingPassive <
204 WebInputEvent::DispatchType::ListenersForcedNonBlockingPassive,
205 "Enum not ordered correctly");
206 return static_cast<WebInputEvent::DispatchType>(
207 std::min(static_cast<int>(type_1), static_cast<int>(type_2)));
208 }
209
210 bool CanCoalesce(const WebTouchEvent& event_to_coalesce,
211 const WebTouchEvent& event) {
212 if (event.type != event_to_coalesce.type ||
213 event.type != WebInputEvent::TouchMove ||
214 event.modifiers != event_to_coalesce.modifiers ||
215 event.touchesLength != event_to_coalesce.touchesLength ||
216 event.touchesLength > WebTouchEvent::touchesLengthCap)
217 return false;
218
219 static_assert(WebTouchEvent::touchesLengthCap <= sizeof(int32_t) * 8U,
220 "suboptimal touchesLengthCap size");
221 // Ensure that we have a 1-to-1 mapping of pointer ids between touches.
222 std::bitset<WebTouchEvent::touchesLengthCap> unmatched_event_touches(
223 (1 << event.touchesLength) - 1);
224 for (unsigned i = 0; i < event_to_coalesce.touchesLength; ++i) {
225 int event_touch_index =
226 GetIndexOfTouchID(event, event_to_coalesce.touches[i].id);
227 if (event_touch_index == kInvalidTouchIndex)
228 return false;
229 if (!unmatched_event_touches[event_touch_index])
230 return false;
231 unmatched_event_touches[event_touch_index] = false;
232 }
233 return unmatched_event_touches.none();
234 }
235
236 void Coalesce(const WebTouchEvent& event_to_coalesce, WebTouchEvent* event) {
237 DCHECK(CanCoalesce(event_to_coalesce, *event));
238 // The WebTouchPoints include absolute position information. So it is
239 // sufficient to simply replace the previous event with the new event->
240 // However, it is necessary to make sure that all the points have the
241 // correct state, i.e. the touch-points that moved in the last event, but
242 // didn't change in the current event, will have Stationary state. It is
243 // necessary to change them back to Moved state.
244 WebTouchEvent old_event = *event;
245 *event = event_to_coalesce;
246 for (unsigned i = 0; i < event->touchesLength; ++i) {
247 int i_old = GetIndexOfTouchID(old_event, event->touches[i].id);
248 if (old_event.touches[i_old].state == blink::WebTouchPoint::StateMoved)
249 event->touches[i].state = blink::WebTouchPoint::StateMoved;
250 }
251 event->movedBeyondSlopRegion |= old_event.movedBeyondSlopRegion;
252 event->dispatchType = MergeDispatchTypes(old_event.dispatchType,
253 event_to_coalesce.dispatchType);
254 }
255
256 bool CanCoalesce(const WebGestureEvent& event_to_coalesce,
257 const WebGestureEvent& event) {
258 if (event.type != event_to_coalesce.type ||
259 event.sourceDevice != event_to_coalesce.sourceDevice ||
260 event.modifiers != event_to_coalesce.modifiers)
261 return false;
262
263 if (event.type == WebInputEvent::GestureScrollUpdate)
264 return true;
265
266 // GesturePinchUpdate scales can be combined only if they share a focal point,
267 // e.g., with double-tap drag zoom.
268 if (event.type == WebInputEvent::GesturePinchUpdate &&
269 event.x == event_to_coalesce.x &&
270 event.y == event_to_coalesce.y)
271 return true;
272
273 return false;
274 }
275
276 void Coalesce(const WebGestureEvent& event_to_coalesce,
277 WebGestureEvent* event) {
278 DCHECK(CanCoalesce(event_to_coalesce, *event));
279 if (event->type == WebInputEvent::GestureScrollUpdate) {
280 event->data.scrollUpdate.deltaX +=
281 event_to_coalesce.data.scrollUpdate.deltaX;
282 event->data.scrollUpdate.deltaY +=
283 event_to_coalesce.data.scrollUpdate.deltaY;
284 DCHECK_EQ(
285 event->data.scrollUpdate.previousUpdateInSequencePrevented,
286 event_to_coalesce.data.scrollUpdate.previousUpdateInSequencePrevented);
287 } else if (event->type == WebInputEvent::GesturePinchUpdate) {
288 event->data.pinchUpdate.scale *= event_to_coalesce.data.pinchUpdate.scale;
289 // Ensure the scale remains bounded above 0 and below Infinity so that
290 // we can reliably perform operations like log on the values.
291 if (event->data.pinchUpdate.scale < numeric_limits<float>::min())
292 event->data.pinchUpdate.scale = numeric_limits<float>::min();
293 else if (event->data.pinchUpdate.scale > numeric_limits<float>::max())
294 event->data.pinchUpdate.scale = numeric_limits<float>::max();
295 }
296 }
297
298 struct WebInputEventToString { 109 struct WebInputEventToString {
299 template <class EventType> 110 template <class EventType>
300 bool Execute(const WebInputEvent& event, std::string* result) const { 111 bool Execute(const WebInputEvent& event, std::string* result) const {
301 SStringPrintf(result, "%s (Time: %lf, Modifiers: %d)\n", 112 SStringPrintf(result, "%s (Time: %lf, Modifiers: %d)\n",
302 WebInputEventTraits::GetName(event.type), 113 WebInputEventTraits::GetName(event.type),
303 event.timeStampSeconds, 114 event.timeStampSeconds,
304 event.modifiers); 115 event.modifiers);
305 const EventType& typed_event = static_cast<const EventType&>(event); 116 const EventType& typed_event = static_cast<const EventType&>(event);
306 ApppendEventDetails(typed_event, result); 117 ApppendEventDetails(typed_event, result);
307 return true; 118 return true;
(...skipping 23 matching lines...) Expand all
331 template <class EventType> 142 template <class EventType>
332 bool Execute(WebInputEvent* event, bool* /* dummy_var */) const { 143 bool Execute(WebInputEvent* event, bool* /* dummy_var */) const {
333 if (!event) 144 if (!event)
334 return false; 145 return false;
335 DCHECK_EQ(sizeof(EventType), event->size); 146 DCHECK_EQ(sizeof(EventType), event->size);
336 delete static_cast<EventType*>(event); 147 delete static_cast<EventType*>(event);
337 return true; 148 return true;
338 } 149 }
339 }; 150 };
340 151
341 struct WebInputEventCanCoalesce {
342 template <class EventType>
343 bool Execute(const WebInputEvent& event_to_coalesce,
344 const WebInputEvent* event) const {
345 if (event_to_coalesce.type != event->type)
346 return false;
347 DCHECK_EQ(sizeof(EventType), event->size);
348 DCHECK_EQ(sizeof(EventType), event_to_coalesce.size);
349 return CanCoalesce(static_cast<const EventType&>(event_to_coalesce),
350 *static_cast<const EventType*>(event));
351 }
352 };
353
354 struct WebInputEventCoalesce {
355 template <class EventType>
356 bool Execute(const WebInputEvent& event_to_coalesce,
357 WebInputEvent* event) const {
358 // New events get coalesced into older events, and the newer timestamp
359 // should always be preserved.
360 const double time_stamp_seconds = event_to_coalesce.timeStampSeconds;
361 Coalesce(static_cast<const EventType&>(event_to_coalesce),
362 static_cast<EventType*>(event));
363 event->timeStampSeconds = time_stamp_seconds;
364 return true;
365 }
366 };
367
368 template <typename Operator, typename ArgIn, typename ArgOut> 152 template <typename Operator, typename ArgIn, typename ArgOut>
369 bool Apply(Operator op, 153 bool Apply(Operator op,
370 WebInputEvent::Type type, 154 WebInputEvent::Type type,
371 const ArgIn& arg_in, 155 const ArgIn& arg_in,
372 ArgOut* arg_out) { 156 ArgOut* arg_out) {
373 if (WebInputEvent::isMouseEventType(type)) 157 if (WebInputEvent::isMouseEventType(type))
374 return op.template Execute<WebMouseEvent>(arg_in, arg_out); 158 return op.template Execute<WebMouseEvent>(arg_in, arg_out);
375 else if (type == WebInputEvent::MouseWheel) 159 else if (type == WebInputEvent::MouseWheel)
376 return op.template Execute<WebMouseWheelEvent>(arg_in, arg_out); 160 return op.template Execute<WebMouseWheelEvent>(arg_in, arg_out);
377 else if (WebInputEvent::isKeyboardEventType(type)) 161 else if (WebInputEvent::isKeyboardEventType(type))
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 return scoped_event; 237 return scoped_event;
454 } 238 }
455 239
456 void WebInputEventTraits::Delete(WebInputEvent* event) { 240 void WebInputEventTraits::Delete(WebInputEvent* event) {
457 if (!event) 241 if (!event)
458 return; 242 return;
459 bool dummy_var = false; 243 bool dummy_var = false;
460 Apply(WebInputEventDelete(), event->type, event, &dummy_var); 244 Apply(WebInputEventDelete(), event->type, event, &dummy_var);
461 } 245 }
462 246
463 bool WebInputEventTraits::CanCoalesce(const WebInputEvent& event_to_coalesce,
464 const WebInputEvent& event) {
465 // Early out before casting.
466 if (event_to_coalesce.type != event.type)
467 return false;
468 return Apply(WebInputEventCanCoalesce(),
469 event.type,
470 event_to_coalesce,
471 &event);
472 }
473
474 void WebInputEventTraits::Coalesce(const WebInputEvent& event_to_coalesce,
475 WebInputEvent* event) {
476 DCHECK(event);
477 Apply(WebInputEventCoalesce(), event->type, event_to_coalesce, event);
478 }
479
480 bool WebInputEventTraits::ShouldBlockEventStream(const WebInputEvent& event) { 247 bool WebInputEventTraits::ShouldBlockEventStream(const WebInputEvent& event) {
481 switch (event.type) { 248 switch (event.type) {
482 case WebInputEvent::MouseDown: 249 case WebInputEvent::MouseDown:
483 case WebInputEvent::MouseUp: 250 case WebInputEvent::MouseUp:
484 case WebInputEvent::MouseEnter: 251 case WebInputEvent::MouseEnter:
485 case WebInputEvent::MouseLeave: 252 case WebInputEvent::MouseLeave:
486 case WebInputEvent::ContextMenu: 253 case WebInputEvent::ContextMenu:
487 case WebInputEvent::GestureScrollBegin: 254 case WebInputEvent::GestureScrollBegin:
488 case WebInputEvent::GestureScrollEnd: 255 case WebInputEvent::GestureScrollEnd:
489 case WebInputEvent::GestureShowPress: 256 case WebInputEvent::GestureShowPress:
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 297
531 uint32_t WebInputEventTraits::GetUniqueTouchEventId( 298 uint32_t WebInputEventTraits::GetUniqueTouchEventId(
532 const WebInputEvent& event) { 299 const WebInputEvent& event) {
533 if (WebInputEvent::isTouchEventType(event.type)) { 300 if (WebInputEvent::isTouchEventType(event.type)) {
534 return static_cast<const WebTouchEvent&>(event).uniqueTouchEventId; 301 return static_cast<const WebTouchEvent&>(event).uniqueTouchEventId;
535 } 302 }
536 return 0U; 303 return 0U;
537 } 304 }
538 305
539 } // namespace content 306 } // namespace content
OLDNEW
« no previous file with comments | « content/common/input/web_input_event_traits.h ('k') | content/common/input/web_input_event_traits_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698