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
3 // found in the LICENSE file.
5 #include "content/common/input/web_input_event_traits.h"
7 #include "base/logging.h"
9 using WebKit::WebGestureEvent;
10 using WebKit::WebInputEvent;
11 using WebKit::WebKeyboardEvent;
12 using WebKit::WebMouseEvent;
13 using WebKit::WebMouseWheelEvent;
14 using WebKit::WebTouchEvent;
19 bool CanCoalesce(const WebKeyboardEvent& event_to_coalesce,
20 const WebKeyboardEvent& event) {
24 void Coalesce(const WebKeyboardEvent& event_to_coalesce,
25 WebKeyboardEvent* event) {
26 DCHECK(CanCoalesce(event_to_coalesce, *event));
29 bool CanCoalesce(const WebMouseEvent& event_to_coalesce,
30 const WebMouseEvent& event) {
31 return event.type == event_to_coalesce.type &&
32 event.type == WebInputEvent::MouseMove;
35 void Coalesce(const WebMouseEvent& event_to_coalesce, WebMouseEvent* event) {
36 DCHECK(CanCoalesce(event_to_coalesce, *event));
37 // Accumulate movement deltas.
38 int x = event->movementX;
39 int y = event->movementY;
40 *event = event_to_coalesce;
41 event->movementX += x;
42 event->movementY += y;
45 bool CanCoalesce(const WebMouseWheelEvent& event_to_coalesce,
46 const WebMouseWheelEvent& event) {
47 return event.modifiers == event_to_coalesce.modifiers &&
48 event.scrollByPage == event_to_coalesce.scrollByPage &&
49 event.phase == event_to_coalesce.phase &&
50 event.momentumPhase == event_to_coalesce.momentumPhase &&
51 event.hasPreciseScrollingDeltas ==
52 event_to_coalesce.hasPreciseScrollingDeltas;
55 float GetUnacceleratedDelta(float accelerated_delta, float acceleration_ratio) {
56 return accelerated_delta * acceleration_ratio;
59 float GetAccelerationRatio(float accelerated_delta, float unaccelerated_delta) {
60 if (unaccelerated_delta == 0.f || accelerated_delta == 0.f)
62 return unaccelerated_delta / accelerated_delta;
65 void Coalesce(const WebMouseWheelEvent& event_to_coalesce,
66 WebMouseWheelEvent* event) {
67 DCHECK(CanCoalesce(event_to_coalesce, *event));
68 float unaccelerated_x =
69 GetUnacceleratedDelta(event->deltaX,
70 event->accelerationRatioX) +
71 GetUnacceleratedDelta(event_to_coalesce.deltaX,
72 event_to_coalesce.accelerationRatioX);
73 float unaccelerated_y =
74 GetUnacceleratedDelta(event->deltaY,
75 event->accelerationRatioY) +
76 GetUnacceleratedDelta(event_to_coalesce.deltaY,
77 event_to_coalesce.accelerationRatioY);
78 event->deltaX += event_to_coalesce.deltaX;
79 event->deltaY += event_to_coalesce.deltaY;
80 event->wheelTicksX += event_to_coalesce.wheelTicksX;
81 event->wheelTicksY += event_to_coalesce.wheelTicksY;
82 event->accelerationRatioX =
83 GetAccelerationRatio(event->deltaX, unaccelerated_x);
84 event->accelerationRatioY =
85 GetAccelerationRatio(event->deltaY, unaccelerated_y);
86 DCHECK_GE(event_to_coalesce.timeStampSeconds, event->timeStampSeconds);
87 event->timeStampSeconds = event_to_coalesce.timeStampSeconds;
90 bool CanCoalesce(const WebTouchEvent& event_to_coalesce,
91 const WebTouchEvent& event) {
92 return event.type == event_to_coalesce.type &&
93 event.type == WebInputEvent::TouchMove &&
94 event.modifiers == event_to_coalesce.modifiers &&
95 event.touchesLength == event_to_coalesce.touchesLength;
98 void Coalesce(const WebTouchEvent& event_to_coalesce, WebTouchEvent* event) {
99 DCHECK(CanCoalesce(event_to_coalesce, *event));
100 // The WebTouchPoints include absolute position information. So it is
101 // sufficient to simply replace the previous event with the new event->
102 // However, it is necessary to make sure that all the points have the
103 // correct state, i.e. the touch-points that moved in the last event, but
104 // didn't change in the current event, will have Stationary state. It is
105 // necessary to change them back to Moved state.
106 WebTouchEvent old_event = *event;
107 *event = event_to_coalesce;
108 for (unsigned i = 0; i < event->touchesLength; ++i) {
109 if (old_event.touches[i].state == WebKit::WebTouchPoint::StateMoved)
110 event->touches[i].state = WebKit::WebTouchPoint::StateMoved;
114 bool CanCoalesce(const WebGestureEvent& event_to_coalesce,
115 const WebGestureEvent& event) {
116 return event.type == event_to_coalesce.type &&
117 event.type == WebInputEvent::GestureScrollUpdate &&
118 event.modifiers == event_to_coalesce.modifiers;
121 void Coalesce(const WebGestureEvent& event_to_coalesce,
122 WebGestureEvent* event) {
123 DCHECK(CanCoalesce(event_to_coalesce, *event));
124 event->data.scrollUpdate.deltaX += event_to_coalesce.data.scrollUpdate.deltaX;
125 event->data.scrollUpdate.deltaY += event_to_coalesce.data.scrollUpdate.deltaY;
128 struct WebInputEventSize {
129 template <class EventType>
130 bool Execute(WebInputEvent::Type /* type */, size_t* type_size) const {
131 *type_size = sizeof(EventType);
136 struct WebInputEventClone {
137 template <class EventType>
138 bool Execute(const WebInputEvent& event,
139 ScopedWebInputEvent* scoped_event) const {
140 DCHECK_EQ(sizeof(EventType), event.size);
141 *scoped_event = ScopedWebInputEvent(
142 new EventType(static_cast<const EventType&>(event)));
147 struct WebInputEventDelete {
148 template <class EventType>
149 bool Execute(WebInputEvent* event, bool* /* dummy_var */) const {
152 DCHECK_EQ(sizeof(EventType), event->size);
153 delete static_cast<EventType*>(event);
158 struct WebInputEventCanCoalesce {
159 template <class EventType>
160 bool Execute(const WebInputEvent& event_to_coalesce,
161 const WebInputEvent* event) const {
162 if (event_to_coalesce.type != event->type)
164 DCHECK_EQ(sizeof(EventType), event->size);
165 DCHECK_EQ(sizeof(EventType), event_to_coalesce.size);
166 return CanCoalesce(static_cast<const EventType&>(event_to_coalesce),
167 *static_cast<const EventType*>(event));
171 struct WebInputEventCoalesce {
172 template <class EventType>
173 bool Execute(const WebInputEvent& event_to_coalesce,
174 WebInputEvent* event) const {
175 Coalesce(static_cast<const EventType&>(event_to_coalesce),
176 static_cast<EventType*>(event));
181 template <typename Operator, typename ArgIn, typename ArgOut>
182 bool Apply(Operator op,
183 WebInputEvent::Type type,
186 if (WebInputEvent::isMouseEventType(type))
187 return op.template Execute<WebMouseEvent>(arg_in, arg_out);
188 else if (type == WebInputEvent::MouseWheel)
189 return op.template Execute<WebMouseWheelEvent>(arg_in, arg_out);
190 else if (WebInputEvent::isKeyboardEventType(type))
191 return op.template Execute<WebKeyboardEvent>(arg_in, arg_out);
192 else if (WebInputEvent::isTouchEventType(type))
193 return op.template Execute<WebTouchEvent>(arg_in, arg_out);
194 else if (WebInputEvent::isGestureEventType(type))
195 return op.template Execute<WebGestureEvent>(arg_in, arg_out);
197 NOTREACHED() << "Unknown webkit event type " << type;
203 const char* WebInputEventTraits::GetName(WebInputEvent::Type type) {
204 #define CASE_TYPE(t) case WebInputEvent::t: return #t
206 CASE_TYPE(Undefined);
207 CASE_TYPE(MouseDown);
209 CASE_TYPE(MouseMove);
210 CASE_TYPE(MouseEnter);
211 CASE_TYPE(MouseLeave);
212 CASE_TYPE(ContextMenu);
213 CASE_TYPE(MouseWheel);
214 CASE_TYPE(RawKeyDown);
218 CASE_TYPE(GestureScrollBegin);
219 CASE_TYPE(GestureScrollEnd);
220 CASE_TYPE(GestureScrollUpdate);
221 CASE_TYPE(GestureFlingStart);
222 CASE_TYPE(GestureFlingCancel);
223 CASE_TYPE(GestureShowPress);
224 CASE_TYPE(GestureTap);
225 CASE_TYPE(GestureTapUnconfirmed);
226 CASE_TYPE(GestureTapDown);
227 CASE_TYPE(GestureTapCancel);
228 CASE_TYPE(GestureDoubleTap);
229 CASE_TYPE(GestureTwoFingerTap);
230 CASE_TYPE(GestureLongPress);
231 CASE_TYPE(GestureLongTap);
232 CASE_TYPE(GesturePinchBegin);
233 CASE_TYPE(GesturePinchEnd);
234 CASE_TYPE(GesturePinchUpdate);
235 CASE_TYPE(TouchStart);
236 CASE_TYPE(TouchMove);
238 CASE_TYPE(TouchCancel);
240 // Must include default to let WebKit::WebInputEvent add new event types
241 // before they're added here.
243 "Unhandled WebInputEvent type in WebInputEventTraits::GetName.\n";
250 size_t WebInputEventTraits::GetSize(WebInputEvent::Type type) {
252 Apply(WebInputEventSize(), type, type, &size);
256 ScopedWebInputEvent WebInputEventTraits::Clone(const WebInputEvent& event) {
257 ScopedWebInputEvent scoped_event;
258 Apply(WebInputEventClone(), event.type, event, &scoped_event);
259 return scoped_event.Pass();
262 void WebInputEventTraits::Delete(WebInputEvent* event) {
265 bool dummy_var = false;
266 Apply(WebInputEventDelete(), event->type, event, &dummy_var);
269 bool WebInputEventTraits::CanCoalesce(const WebInputEvent& event_to_coalesce,
270 const WebInputEvent& event) {
271 // Early out before casting.
272 if (event_to_coalesce.type != event.type)
274 return Apply(WebInputEventCanCoalesce(),
280 void WebInputEventTraits::Coalesce(const WebInputEvent& event_to_coalesce,
281 WebInputEvent* event) {
283 Apply(WebInputEventCoalesce(), event->type, event_to_coalesce, event);
286 } // namespace content