Avoid the Vector<> copy in WebTouchEvent constructor
[WebKit-https.git] / Source / WebKit2 / Shared / efl / WebEventFactory.cpp
1 /*
2  * Copyright (C) 2011 Samsung Electronics
3  * Copyright (C) 2012 Intel Corporation
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "WebEventFactory.h"
29
30 #include "EflKeyboardUtilities.h"
31 #include <WebCore/AffineTransform.h>
32 #include <WebCore/Scrollbar.h>
33
34 #if ENABLE(TOUCH_EVENTS)
35 #include "APIArray.h"
36 #include "EwkTouchEvent.h"
37 #include "EwkTouchPoint.h"
38 #include "WKAPICast.h"
39 #endif
40
41 using namespace WebCore;
42
43 namespace WebKit {
44
45 enum {
46     VerticalScrollDirection = 0,
47     HorizontalScrollDirection = 1
48 };
49
50 enum {
51     LeftButton = 1,
52     MiddleButton = 2,
53     RightButton = 3
54 };
55
56 static const char keyPadPrefix[] = "KP_";
57
58 static inline WebEvent::Modifiers modifiersForEvent(const Evas_Modifier* modifiers)
59 {
60     unsigned result = 0;
61
62     if (evas_key_modifier_is_set(modifiers, "Shift"))
63         result |= WebEvent::ShiftKey;
64     if (evas_key_modifier_is_set(modifiers, "Control"))
65         result |= WebEvent::ControlKey;
66     if (evas_key_modifier_is_set(modifiers, "Alt"))
67         result |= WebEvent::AltKey;
68     if (evas_key_modifier_is_set(modifiers, "Meta"))
69         result |= WebEvent::MetaKey;
70
71     return static_cast<WebEvent::Modifiers>(result);
72 }
73
74 static inline WebMouseEvent::Button buttonForEvent(int button)
75 {
76     if (button == LeftButton)
77         return WebMouseEvent::LeftButton;
78     if (button == MiddleButton)
79         return WebMouseEvent::MiddleButton;
80     if (button == RightButton)
81         return WebMouseEvent::RightButton;
82
83     return WebMouseEvent::NoButton;
84 }
85
86 static inline int clickCountForEvent(const Evas_Button_Flags flags)
87 {
88     if (flags & EVAS_BUTTON_TRIPLE_CLICK)
89         return 3;
90     if (flags & EVAS_BUTTON_DOUBLE_CLICK)
91         return 2;
92
93     return 1;
94 }
95
96 static inline double convertMillisecondToSecond(unsigned timestamp)
97 {
98     return static_cast<double>(timestamp) / 1000;
99 }
100
101 WebMouseEvent WebEventFactory::createWebMouseEvent(const Evas_Event_Mouse_Down* event, const AffineTransform& toWebContent, const AffineTransform& toDeviceScreen)
102 {
103     IntPoint pos(event->canvas.x, event->canvas.y);
104     return WebMouseEvent(WebEvent::MouseDown,
105         buttonForEvent(event->button),
106         toWebContent.mapPoint(pos),
107         toDeviceScreen.mapPoint(pos),
108         0 /* deltaX */,
109         0 /* deltaY */,
110         0 /* deltaZ */,
111         clickCountForEvent(event->flags),
112         modifiersForEvent(event->modifiers),
113         convertMillisecondToSecond(event->timestamp));
114 }
115
116 WebMouseEvent WebEventFactory::createWebMouseEvent(const Evas_Event_Mouse_Up* event, const AffineTransform& toWebContent, const AffineTransform& toDeviceScreen)
117 {
118     IntPoint pos(event->canvas.x, event->canvas.y);
119     return WebMouseEvent(WebEvent::MouseUp,
120         buttonForEvent(event->button),
121         toWebContent.mapPoint(pos),
122         toDeviceScreen.mapPoint(pos),
123         0 /* deltaX */,
124         0 /* deltaY */,
125         0 /* deltaZ */,
126         clickCountForEvent(event->flags),
127         modifiersForEvent(event->modifiers),
128         convertMillisecondToSecond(event->timestamp));
129 }
130
131 WebMouseEvent WebEventFactory::createWebMouseEvent(const Evas_Event_Mouse_Move* event, const AffineTransform& toWebContent, const AffineTransform& toDeviceScreen)
132 {
133     IntPoint pos(event->cur.canvas.x, event->cur.canvas.y);
134     return WebMouseEvent(WebEvent::MouseMove,
135         buttonForEvent(event->buttons),
136         toWebContent.mapPoint(pos),
137         toDeviceScreen.mapPoint(pos),
138         (event->cur.canvas.x - event->prev.canvas.x) /* deltaX */,
139         (event->cur.canvas.y - event->prev.canvas.y) /* deltaY */,
140         0 /* deltaZ */,
141         0 /* clickCount */,
142         modifiersForEvent(event->modifiers),
143         convertMillisecondToSecond(event->timestamp));
144 }
145
146 WebWheelEvent WebEventFactory::createWebWheelEvent(const Evas_Event_Mouse_Wheel* event, const AffineTransform& toWebContent, const AffineTransform& toDeviceScreen)
147 {
148     float deltaX = 0;
149     float deltaY = 0;
150     float wheelTicksX = 0;
151     float wheelTicksY = 0;
152
153     // A negative z value means (in EFL) that we are scrolling down, so we need
154     // to invert the value.
155     if (event->direction == VerticalScrollDirection) {
156         deltaX = 0;
157         deltaY = - event->z;
158     } else if (event->direction == HorizontalScrollDirection) {
159         deltaX = - event->z;
160         deltaY = 0;
161     }
162
163     wheelTicksX = deltaX;
164     wheelTicksY = deltaY;
165     deltaX *= static_cast<float>(Scrollbar::pixelsPerLineStep());
166     deltaY *= static_cast<float>(Scrollbar::pixelsPerLineStep());
167
168     IntPoint pos(event->canvas.x, event->canvas.y);
169
170     return WebWheelEvent(WebEvent::Wheel,
171         toWebContent.mapPoint(pos),
172         toDeviceScreen.mapPoint(pos),
173         FloatSize(deltaX, deltaY),
174         FloatSize(wheelTicksX, wheelTicksY),
175         WebWheelEvent::ScrollByPixelWheelEvent,
176         modifiersForEvent(event->modifiers),
177         convertMillisecondToSecond(event->timestamp));
178 }
179
180 WebKeyboardEvent WebEventFactory::createWebKeyboardEvent(const Evas_Event_Key_Down* event)
181 {
182     const String keyName(event->key);
183     return WebKeyboardEvent(WebEvent::KeyDown,
184         String::fromUTF8(event->string),
185         String::fromUTF8(event->string),
186         keyIdentifierForEvasKeyName(keyName),
187         windowsKeyCodeForEvasKeyName(keyName),
188         0 /* FIXME: nativeVirtualKeyCode */,
189         0 /* macCharCode */,
190         false /* FIXME: isAutoRepeat */,
191         keyName.startsWith(keyPadPrefix),
192         false /* isSystemKey */,
193         modifiersForEvent(event->modifiers),
194         convertMillisecondToSecond(event->timestamp));
195 }
196
197 WebKeyboardEvent WebEventFactory::createWebKeyboardEvent(const Evas_Event_Key_Up* event)
198 {
199     const String keyName(event->key);
200     return WebKeyboardEvent(WebEvent::KeyUp,
201         String::fromUTF8(event->string),
202         String::fromUTF8(event->string),
203         keyIdentifierForEvasKeyName(keyName),
204         windowsKeyCodeForEvasKeyName(keyName),
205         0 /* FIXME: nativeVirtualKeyCode */,
206         0 /* macCharCode */,
207         false /* FIXME: isAutoRepeat */,
208         keyName.startsWith(keyPadPrefix),
209         false /* isSystemKey */,
210         modifiersForEvent(event->modifiers),
211         convertMillisecondToSecond(event->timestamp));
212 }
213
214 #if ENABLE(TOUCH_EVENTS)
215 static inline WebPlatformTouchPoint::TouchPointState toWebPlatformTouchPointState(WKTouchPointState state)
216 {
217     switch (state) {
218     case kWKTouchPointStateTouchReleased:
219         return WebPlatformTouchPoint::TouchReleased;
220     case kWKTouchPointStateTouchMoved:
221         return WebPlatformTouchPoint::TouchMoved;
222     case kWKTouchPointStateTouchPressed:
223         return WebPlatformTouchPoint::TouchPressed;
224     case kWKTouchPointStateTouchStationary:
225         return WebPlatformTouchPoint::TouchStationary;
226     case kWKTouchPointStateTouchCancelled:
227     default:
228         return WebPlatformTouchPoint::TouchCancelled;
229     }
230 }
231
232 static inline WebEvent::Type toWebEventType(WKEventType type)
233 {
234     switch (type) {
235     case kWKEventTypeTouchStart:
236         return WebEvent::TouchStart;
237     case kWKEventTypeTouchMove:
238         return WebEvent::TouchMove;
239     case kWKEventTypeTouchEnd:
240         return WebEvent::TouchEnd;
241     case kWKEventTypeTouchCancel:
242         return WebEvent::TouchCancel;
243     default:
244         return WebEvent::NoType;
245     }
246
247 }
248
249 static inline WebEvent::Modifiers toWebEventModifiers(unsigned modifiers)
250 {
251     unsigned result = 0;
252
253     if (modifiers & kWKEventModifiersShiftKey)
254         result |= WebEvent::ShiftKey;
255     if (modifiers & kWKEventModifiersControlKey)
256         result |= WebEvent::ControlKey;
257     if (modifiers & kWKEventModifiersAltKey)
258         result |= WebEvent::AltKey;
259     if (modifiers & kWKEventModifiersMetaKey)
260         result |= WebEvent::MetaKey;
261
262     return static_cast<WebEvent::Modifiers>(result);
263 }
264
265 WebTouchEvent WebEventFactory::createWebTouchEvent(const EwkTouchEvent* event, const AffineTransform& toWebContent)
266 {
267     API::Array* touchPointsArray = toImpl(event->touchPoints());
268     size_t size = touchPointsArray->size();
269
270     Vector<WebPlatformTouchPoint> touchPoints;
271     touchPoints.reserveInitialCapacity(size);
272
273     for (size_t i = 0; i < size; ++i) {
274         if (EwkTouchPoint* point = touchPointsArray->at<EwkTouchPoint>(i))
275             touchPoints.uncheckedAppend(WebPlatformTouchPoint(point->id(), toWebPlatformTouchPointState(point->state()), toIntPoint(point->screenPosition()), toWebContent.mapPoint(toIntPoint(point->position())), toIntSize(point->radius()), point->rotationAngle(), point->forceFactor()));
276     }
277
278     return WebTouchEvent(toWebEventType(event->eventType()), WTF::move(touchPoints), toWebEventModifiers(event->modifiers()), event->timestamp());
279 }
280 #endif
281
282 } // namespace WebKit