- add sources.
[platform/framework/web/crosswalk.git] / src / content / common / input / web_input_event_traits.cc
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.
4
5 #include "content/common/input/web_input_event_traits.h"
6
7 #include "base/logging.h"
8
9 using WebKit::WebGestureEvent;
10 using WebKit::WebInputEvent;
11 using WebKit::WebKeyboardEvent;
12 using WebKit::WebMouseEvent;
13 using WebKit::WebMouseWheelEvent;
14 using WebKit::WebTouchEvent;
15
16 namespace content {
17 namespace {
18
19 bool CanCoalesce(const WebKeyboardEvent& event_to_coalesce,
20                  const WebKeyboardEvent& event) {
21   return false;
22 }
23
24 void Coalesce(const WebKeyboardEvent& event_to_coalesce,
25               WebKeyboardEvent* event) {
26   DCHECK(CanCoalesce(event_to_coalesce, *event));
27 }
28
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;
33 }
34
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;
43 }
44
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;
53 }
54
55 float GetUnacceleratedDelta(float accelerated_delta, float acceleration_ratio) {
56   return accelerated_delta * acceleration_ratio;
57 }
58
59 float GetAccelerationRatio(float accelerated_delta, float unaccelerated_delta) {
60   if (unaccelerated_delta == 0.f || accelerated_delta == 0.f)
61     return 1.f;
62   return unaccelerated_delta / accelerated_delta;
63 }
64
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;
88 }
89
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;
96 }
97
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;
111   }
112 }
113
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;
119 }
120
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;
126 }
127
128 struct WebInputEventSize {
129   template <class EventType>
130   bool Execute(WebInputEvent::Type /* type */, size_t* type_size) const {
131     *type_size = sizeof(EventType);
132     return true;
133   }
134 };
135
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)));
143     return true;
144   }
145 };
146
147 struct WebInputEventDelete {
148   template <class EventType>
149   bool Execute(WebInputEvent* event, bool* /* dummy_var */) const {
150     if (!event)
151       return false;
152     DCHECK_EQ(sizeof(EventType), event->size);
153     delete static_cast<EventType*>(event);
154     return true;
155   }
156 };
157
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)
163       return false;
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));
168   }
169 };
170
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));
177     return true;
178   }
179 };
180
181 template <typename Operator, typename ArgIn, typename ArgOut>
182 bool Apply(Operator op,
183            WebInputEvent::Type type,
184            const ArgIn& arg_in,
185            ArgOut* arg_out) {
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);
196
197   NOTREACHED() << "Unknown webkit event type " << type;
198   return false;
199 }
200
201 }  // namespace
202
203 const char* WebInputEventTraits::GetName(WebInputEvent::Type type) {
204 #define CASE_TYPE(t) case WebInputEvent::t:  return #t
205   switch(type) {
206     CASE_TYPE(Undefined);
207     CASE_TYPE(MouseDown);
208     CASE_TYPE(MouseUp);
209     CASE_TYPE(MouseMove);
210     CASE_TYPE(MouseEnter);
211     CASE_TYPE(MouseLeave);
212     CASE_TYPE(ContextMenu);
213     CASE_TYPE(MouseWheel);
214     CASE_TYPE(RawKeyDown);
215     CASE_TYPE(KeyDown);
216     CASE_TYPE(KeyUp);
217     CASE_TYPE(Char);
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);
237     CASE_TYPE(TouchEnd);
238     CASE_TYPE(TouchCancel);
239     default:
240       // Must include default to let WebKit::WebInputEvent add new event types
241       // before they're added here.
242       DLOG(WARNING) <<
243           "Unhandled WebInputEvent type in WebInputEventTraits::GetName.\n";
244       break;
245   }
246 #undef CASE_TYPE
247   return "";
248 }
249
250 size_t WebInputEventTraits::GetSize(WebInputEvent::Type type) {
251   size_t size = 0;
252   Apply(WebInputEventSize(), type, type, &size);
253   return size;
254 }
255
256 ScopedWebInputEvent WebInputEventTraits::Clone(const WebInputEvent& event) {
257   ScopedWebInputEvent scoped_event;
258   Apply(WebInputEventClone(), event.type, event, &scoped_event);
259   return scoped_event.Pass();
260 }
261
262 void WebInputEventTraits::Delete(WebInputEvent* event) {
263   if (!event)
264     return;
265   bool dummy_var = false;
266   Apply(WebInputEventDelete(), event->type, event, &dummy_var);
267 }
268
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)
273     return false;
274   return Apply(WebInputEventCanCoalesce(),
275                event.type,
276                event_to_coalesce,
277                &event);
278 }
279
280 void WebInputEventTraits::Coalesce(const WebInputEvent& event_to_coalesce,
281                                    WebInputEvent* event) {
282   DCHECK(event);
283   Apply(WebInputEventCoalesce(), event->type, event_to_coalesce, event);
284 }
285
286 }  // namespace content