Tizen 2.1 base
[framework/web/webkit-efl.git] / Source / WebKit2 / UIProcess / API / efl / tizen / GestureRecognizer.cpp
1 /*
2  * Copyright (C) 2011 Samsung Electronics
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "GestureRecognizer.h"
28
29 #include <WebCore/IntSize.h>
30 #include <WebCore/IntPoint.h>
31
32 using namespace WebCore;
33
34 namespace WebKit {
35
36 const double GestureRecognizer::s_thumbscrollMomentumThreshold = 400;
37
38 static int getPointDistanceSquare(const IntPoint& point1, const IntPoint& point2)
39 {
40     int xDistance = point1.x() - point2.x();
41     int yDistance = point1.y() - point2.y();
42     return xDistance * xDistance + yDistance * yDistance;
43 }
44
45 GestureRecognizer::GestureRecognizer(Evas_Object* ewkView)
46     : m_viewWidget(ewkView)
47     , m_pressedPoint()
48     , m_currentPoint()
49     , m_isTapScheduled(false)
50     , m_isLongTapProcessed(false)
51     , m_longTapCount(0)
52 {
53     ASSERT(m_viewWidget);
54
55     m_gestureObject = elm_gesture_layer_add(m_viewWidget);
56     elm_gesture_layer_hold_events_set(m_gestureObject, false);
57     elm_gesture_layer_attach(m_gestureObject, m_viewWidget);
58     ecore_animator_frametime_set(1.0 / s_defaultFramerate); // it should be done in the application??
59     elm_config_scroll_thumbscroll_momentum_threshold_set(s_thumbscrollMomentumThreshold);
60     initializeCallbacks();
61 }
62
63 GestureRecognizer::~GestureRecognizer()
64 {
65     if (m_gestureObject)
66         evas_object_del(m_gestureObject);
67
68     evas_object_event_callback_del(m_viewWidget, EVAS_CALLBACK_MOUSE_UP, onMouseUp);
69 }
70
71 void GestureRecognizer::initializeCallbacks()
72 {
73     // Add gesture callbacks.
74     elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_TAPS, ELM_GESTURE_STATE_START, onTapStart, this);
75     elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_TAPS, ELM_GESTURE_STATE_ABORT, onTapAbort, this);
76     elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_TAPS, ELM_GESTURE_STATE_END, onTapEnd, this);
77     elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_LONG_TAPS, ELM_GESTURE_STATE_START, onLongTapStart, this);
78     elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_LONG_TAPS, ELM_GESTURE_STATE_MOVE, onLongTapMove, this);
79     elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_LONG_TAPS, ELM_GESTURE_STATE_END, onLongTapEnd, this);
80     elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_LONG_TAPS, ELM_GESTURE_STATE_ABORT, onLongTapEnd, this);
81     elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_DOUBLE_TAPS, ELM_GESTURE_STATE_END, onDoubleTapEnd, this);
82
83     elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_START, onMomentumStart, this);
84     elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_MOVE, onMomentumMove, this);
85     elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_END, onMomentumEnd, this);
86     elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_ABORT, onMomentumAbort, this);
87     elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_START, onZoomStart, this);
88
89     elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_MOVE, onZoomMove, this);
90     elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_END, onZoomEnd, this);
91     elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_ABORT, onZoomEnd, this);
92
93     // add evas callbacks.
94     evas_object_event_callback_add(m_viewWidget, EVAS_CALLBACK_MOUSE_UP, onMouseUp, this);
95 }
96
97 Evas_Event_Flags GestureRecognizer::onTapStart(void* data, void* eventInfo)
98 {
99     static_cast<GestureRecognizer*>(data)->startTap(static_cast<Elm_Gesture_Taps_Info*>(eventInfo));
100     return EVAS_EVENT_FLAG_NONE;
101 }
102
103 Evas_Event_Flags GestureRecognizer::onTapEnd(void* data, void* eventInfo)
104 {
105     static_cast<GestureRecognizer*>(data)->endTap(static_cast<Elm_Gesture_Taps_Info*>(eventInfo));
106     return EVAS_EVENT_FLAG_NONE;
107 }
108
109 Evas_Event_Flags GestureRecognizer::onTapAbort(void* data, void* eventInfo)
110 {
111     static_cast<GestureRecognizer*>(data)->abortTap(static_cast<Elm_Gesture_Taps_Info*>(eventInfo));
112     return EVAS_EVENT_FLAG_NONE;
113 }
114
115 Evas_Event_Flags GestureRecognizer::onLongTapStart(void* data, void* eventInfo)
116 {
117     static_cast<GestureRecognizer*>(data)->startLongTap(static_cast<Elm_Gesture_Taps_Info*>(eventInfo));
118     return EVAS_EVENT_FLAG_NONE;
119 }
120
121 Evas_Event_Flags GestureRecognizer::onLongTapMove(void* data, void* eventInfo)
122 {
123     static_cast<GestureRecognizer*>(data)->moveLongTap(static_cast<Elm_Gesture_Taps_Info*>(eventInfo));
124     return EVAS_EVENT_FLAG_NONE;
125 }
126
127 Evas_Event_Flags GestureRecognizer::onLongTapEnd(void* data, void* eventInfo)
128 {
129     static_cast<GestureRecognizer*>(data)->endLongTap(static_cast<Elm_Gesture_Taps_Info*>(eventInfo));
130     return EVAS_EVENT_FLAG_NONE;
131 }
132
133 Evas_Event_Flags GestureRecognizer::onDoubleTapEnd(void* data, void* eventInfo)
134 {
135     static_cast<GestureRecognizer*>(data)->endDoubleTap(static_cast<Elm_Gesture_Taps_Info*>(eventInfo));
136     return EVAS_EVENT_FLAG_NONE;
137 }
138
139 Evas_Event_Flags GestureRecognizer::onMomentumStart(void* data, void* eventInfo)
140 {
141     static_cast<GestureRecognizer*>(data)->startMomentum(static_cast<Elm_Gesture_Momentum_Info*>(eventInfo));
142     return EVAS_EVENT_FLAG_NONE;
143 }
144
145 Evas_Event_Flags GestureRecognizer::onMomentumMove(void* data, void* eventInfo)
146 {
147     static_cast<GestureRecognizer*>(data)->moveMomentum(static_cast<Elm_Gesture_Momentum_Info*>(eventInfo));
148     return EVAS_EVENT_FLAG_NONE;
149 }
150
151 Evas_Event_Flags GestureRecognizer::onMomentumEnd(void* data, void* eventInfo)
152 {
153     static_cast<GestureRecognizer*>(data)->endMomentum(static_cast<Elm_Gesture_Momentum_Info*>(eventInfo));
154     return EVAS_EVENT_FLAG_NONE;
155 }
156
157 Evas_Event_Flags GestureRecognizer::onMomentumAbort(void* data, void* eventInfo)
158 {
159     Elm_Gesture_Momentum_Info* event = static_cast<Elm_Gesture_Momentum_Info*>(eventInfo);
160     // Set momentum value to 0 because momentum is aborted.
161     event->mx = 0;
162     event->my = 0;
163     static_cast<GestureRecognizer*>(data)->endMomentum(event);
164     return EVAS_EVENT_FLAG_NONE;
165 }
166
167 Evas_Event_Flags GestureRecognizer::onZoomStart(void* data, void* eventInfo)
168 {
169     static_cast<GestureRecognizer*>(data)->startZoom(static_cast<Elm_Gesture_Zoom_Info*>(eventInfo));
170     return EVAS_EVENT_FLAG_NONE;
171 }
172
173 void GestureRecognizer::onMouseUp(void* data, Evas*, Evas_Object*, void* eventInfo)
174 {
175     Evas_Event_Mouse_Up* event = static_cast<Evas_Event_Mouse_Up*>(eventInfo);
176     static_cast<GestureRecognizer*>(data)->processScheduledTap(event->canvas.x, event->canvas.y, event->timestamp);
177 }
178
179 void GestureRecognizer::startTap(Elm_Gesture_Taps_Info* event)
180 {
181     m_currentPoint = m_pressedPoint = IntPoint(event->x, event->y);
182
183     setTapScheduled(false);
184     m_isLongTapProcessed = false;
185     startGesture(EWK_GESTURE_TAP, IntPoint(event->x, event->y), IntPoint(), 1, 1);
186 }
187
188 void GestureRecognizer::endTap(Elm_Gesture_Taps_Info* event)
189 {
190     if (event->n != 1)
191         return;
192
193     m_currentPoint = IntPoint(event->x, event->y);
194     processTap(event->x, event->y, event->timestamp);
195 }
196
197 void GestureRecognizer::abortTap(Elm_Gesture_Taps_Info* event)
198 {
199     // The elm_gesture_layer aborts tap when 0.4 second is passed, but we want to process tap after 0.4 second.
200     // So, I set isTapScheduled to true to process tap when mouse up.
201     if (event->n == 1) // Tap is aborted after 0.4 second.
202         setTapScheduled(true);
203     else // Tap is aborted by moving before 0.4 second.
204         setTapScheduled(false);
205 }
206
207 void GestureRecognizer::processTap(int x, int y, unsigned int timestamp)
208 {
209     endGesture(EWK_GESTURE_TAP, IntPoint(x, y), IntPoint(), 1, 1);
210     setTapScheduled(false);
211 }
212
213 void GestureRecognizer::processScheduledTap(int x, int y, unsigned int timestamp)
214 {
215     if (m_isTapScheduled)
216         processTap(x, y, timestamp);
217 }
218
219 void GestureRecognizer::startLongTap(Elm_Gesture_Taps_Info* event)
220 {
221     m_longTapCount = 0;
222 }
223
224 void GestureRecognizer::moveLongTap(Elm_Gesture_Taps_Info* event)
225 {
226     m_longTapCount++;
227
228     // We have to process only first movement as a long tap.
229     if (m_longTapCount != 1 || event->n != 1)
230         return;
231
232     setTapScheduled(false);
233
234     startGesture(EWK_GESTURE_LONG_PRESS, IntPoint(event->x, event->y), IntPoint(), 1, 1);
235     m_isLongTapProcessed = true;
236 }
237
238 void GestureRecognizer::endLongTap(Elm_Gesture_Taps_Info* event)
239 {
240     if (event->n != 1 || !m_isLongTapProcessed)
241         return;
242
243     endGesture(EWK_GESTURE_LONG_PRESS, IntPoint(event->x, event->y), IntPoint(), 1, 1);
244 }
245
246 void GestureRecognizer::endDoubleTap(Elm_Gesture_Taps_Info* event)
247 {
248     if (event->n != 1)
249         return;
250
251     // We do not process tap after double tap occurs.
252     setTapScheduled(false);
253
254     endGesture(EWK_GESTURE_TAP, IntPoint(event->x, event->y), IntPoint(), 1, 2);
255 }
256
257 // The isTapScheduled will be set to true when tap is aborted,
258 // and set to false when zoom, pan, double tap and long tap is occured.
259 // Additionally, focus will be set when focus timer is expired,
260 // and will be clear when tap is processed or we don't want to process scheduled tap.
261 void GestureRecognizer::setTapScheduled(bool scheduled)
262 {
263     m_isTapScheduled = scheduled;
264 }
265
266 void GestureRecognizer::startMomentum(Elm_Gesture_Momentum_Info* event)
267 {
268     if (event->n != 1)
269         return;
270
271     startGesture(EWK_GESTURE_PAN, IntPoint(event->x2, event->y2), IntPoint(), 1, 1);
272 }
273
274 void GestureRecognizer::moveMomentum(Elm_Gesture_Momentum_Info* event)
275 {
276     if (event->n != 1)
277         return;
278
279     m_currentPoint = IntPoint(event->x2, event->y2);
280
281     if (m_isTapScheduled && (getPointDistanceSquare(m_pressedPoint, m_currentPoint) > s_tapThreshold))
282         setTapScheduled(false);
283
284     moveGesture(EWK_GESTURE_PAN, m_currentPoint, IntPoint(event->mx, event->my), 1, 1);
285 }
286
287 void GestureRecognizer::endMomentum(Elm_Gesture_Momentum_Info* event)
288 {
289     endGesture(EWK_GESTURE_PAN, IntPoint(event->x2, event->y2), IntPoint(event->mx, event->my), 1, 1);
290     if (event->n != 1)
291         return;
292
293     startGesture(EWK_GESTURE_FLICK, IntPoint(event->x2, event->y2), IntPoint(event->mx, event->my), 1, 1);
294 }
295
296 void GestureRecognizer::startZoom(Elm_Gesture_Zoom_Info* event)
297 {
298     setTapScheduled(false);
299     startGesture(EWK_GESTURE_PINCH, IntPoint(event->x, event->y), IntPoint(), event->zoom, 1);
300 }
301
302 Evas_Event_Flags GestureRecognizer::onZoomMove(void* data, void* eventInfo)
303 {
304     static_cast<GestureRecognizer*>(data)->moveZoom(static_cast<Elm_Gesture_Zoom_Info*>(eventInfo));
305     return EVAS_EVENT_FLAG_NONE;
306 }
307
308 Evas_Event_Flags GestureRecognizer::onZoomEnd(void* data, void* eventInfo)
309 {
310     static_cast<GestureRecognizer*>(data)->endZoom(static_cast<Elm_Gesture_Zoom_Info*>(eventInfo));
311     return EVAS_EVENT_FLAG_NONE;
312 }
313
314 void GestureRecognizer::moveZoom(Elm_Gesture_Zoom_Info* event)
315 {
316     moveGesture(EWK_GESTURE_PINCH, IntPoint(event->x, event->y), IntPoint(), event->zoom, 1);
317 }
318
319 void GestureRecognizer::endZoom(Elm_Gesture_Zoom_Info* event)
320 {
321     endGesture(EWK_GESTURE_PINCH, IntPoint(event->x, event->y), IntPoint(), event->zoom, 1);
322 }
323
324 void GestureRecognizer::startGesture(Ewk_Gesture_Type type, const IntPoint& position, const IntPoint& velocity, double scale, int count)
325 {
326     const Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(m_viewWidget));
327     EINA_SAFETY_ON_NULL_RETURN(smartData->api);
328     EINA_SAFETY_ON_NULL_RETURN(smartData->api->gesture_start);
329
330     Ewk_Event_Gesture gestureEvent;
331     memset(&gestureEvent, 0, sizeof(Ewk_Event_Gesture));
332     gestureEvent.type = type;
333     gestureEvent.position.x = position.x();
334     gestureEvent.position.y = position.y();
335     gestureEvent.velocity.x = velocity.x();
336     gestureEvent.velocity.y = velocity.y();
337     gestureEvent.scale = scale;
338     gestureEvent.count = count;
339     gestureEvent.timestamp = ecore_time_get() * 1000;
340
341     smartData->api->gesture_start(const_cast<Ewk_View_Smart_Data*>(smartData), &gestureEvent);
342 }
343
344 void GestureRecognizer::endGesture(Ewk_Gesture_Type type, const IntPoint& position, const IntPoint& velocity, double scale, int count)
345 {
346     const Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(m_viewWidget));
347     EINA_SAFETY_ON_NULL_RETURN(smartData->api);
348     EINA_SAFETY_ON_NULL_RETURN(smartData->api->gesture_end);
349
350     Ewk_Event_Gesture gestureEvent;
351     memset(&gestureEvent, 0, sizeof(Ewk_Event_Gesture));
352     gestureEvent.type = type;
353     gestureEvent.position.x = position.x();
354     gestureEvent.position.y = position.y();
355     gestureEvent.velocity.x = velocity.x();
356     gestureEvent.velocity.y = velocity.y();
357     gestureEvent.scale = scale;
358     gestureEvent.count = count;
359     gestureEvent.timestamp = ecore_time_get() * 1000;
360
361     smartData->api->gesture_end(const_cast<Ewk_View_Smart_Data*>(smartData), &gestureEvent);
362 }
363
364 void GestureRecognizer::moveGesture(Ewk_Gesture_Type type, const IntPoint& position, const IntPoint& velocity, double scale, int count)
365 {
366     const Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(m_viewWidget));
367     EINA_SAFETY_ON_NULL_RETURN(smartData->api);
368     EINA_SAFETY_ON_NULL_RETURN(smartData->api->gesture_move);
369
370     Ewk_Event_Gesture gestureEvent;
371     memset(&gestureEvent, 0, sizeof(Ewk_Event_Gesture));
372     gestureEvent.type = type;
373     gestureEvent.position.x = position.x();
374     gestureEvent.position.y = position.y();
375     gestureEvent.velocity.x = velocity.x();
376     gestureEvent.velocity.y = velocity.y();
377     gestureEvent.scale = scale;
378     gestureEvent.count = count;
379     gestureEvent.timestamp = ecore_time_get() * 1000;
380
381     smartData->api->gesture_move(const_cast<Ewk_View_Smart_Data*>(smartData), &gestureEvent);
382 }
383
384 } // namespace WebKit