2 * Copyright (C) 2011 Samsung Electronics
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "GestureRecognizer.h"
29 #if ENABLE(TIZEN_DESKTOP_BROWSING)
30 #include "NativeWebMouseEvent.h"
33 #include <WebCore/IntSize.h>
34 #include <WebCore/IntPoint.h>
36 using namespace WebCore;
40 const double GestureRecognizer::s_thumbscrollMomentumThreshold = 400;
42 static int getPointDistanceSquare(const IntPoint& point1, const IntPoint& point2)
44 int xDistance = point1.x() - point2.x();
45 int yDistance = point1.y() - point2.y();
46 return xDistance * xDistance + yDistance * yDistance;
49 GestureRecognizer::GestureRecognizer(Evas_Object* ewkView)
50 : m_viewWidget(ewkView)
53 , m_isTapScheduled(false)
54 , m_isLongTapProcessed(false)
59 m_gestureObject = elm_gesture_layer_add(m_viewWidget);
60 elm_gesture_layer_hold_events_set(m_gestureObject, false);
61 elm_gesture_layer_attach(m_gestureObject, m_viewWidget);
62 elm_gesture_layer_zoom_distance_tolerance_set(m_gestureObject, 0);
63 elm_gesture_layer_double_tap_timeout_set(m_gestureObject, 0.4);
64 ecore_animator_frametime_set(1.0 / s_defaultFramerate); // it should be done in the application??
65 elm_config_scroll_thumbscroll_momentum_threshold_set(s_thumbscrollMomentumThreshold);
66 initializeCallbacks();
69 GestureRecognizer::~GestureRecognizer()
71 // Delete gesture callbacks.
72 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_TAPS, ELM_GESTURE_STATE_START, 0, 0);
73 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_TAPS, ELM_GESTURE_STATE_ABORT, 0, 0);
74 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_TAPS, ELM_GESTURE_STATE_END, 0, 0);
75 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_LONG_TAPS, ELM_GESTURE_STATE_START, 0, 0);
76 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_LONG_TAPS, ELM_GESTURE_STATE_MOVE, 0, 0);
77 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_LONG_TAPS, ELM_GESTURE_STATE_END, 0, 0);
78 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_LONG_TAPS, ELM_GESTURE_STATE_ABORT, 0, 0);
79 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_DOUBLE_TAPS, ELM_GESTURE_STATE_END, 0, 0);
80 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_START, 0, 0);
81 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_MOVE, 0, 0);
82 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_END, 0, 0);
83 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_ABORT, 0, 0);
84 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_START, 0, 0);
85 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_MOVE, 0, 0);
86 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_END, 0, 0);
87 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_ABORT, 0, 0);
90 evas_object_del(m_gestureObject);
92 evas_object_event_callback_del(m_viewWidget, EVAS_CALLBACK_MOUSE_UP, onMouseUp);
94 #if ENABLE(TIZEN_DESKTOP_BROWSING)
95 evas_object_event_callback_del(m_viewWidget, EVAS_CALLBACK_MOUSE_MOVE, onMouseMove);
96 evas_object_event_callback_del(m_viewWidget, EVAS_CALLBACK_MOUSE_DOWN, onMouseDown);
100 void GestureRecognizer::initializeCallbacks()
102 // Add gesture callbacks.
103 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_TAPS, ELM_GESTURE_STATE_START, onTapStart, this);
104 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_TAPS, ELM_GESTURE_STATE_ABORT, onTapAbort, this);
105 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_TAPS, ELM_GESTURE_STATE_END, onTapEnd, this);
106 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_LONG_TAPS, ELM_GESTURE_STATE_START, onLongTapStart, this);
107 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_LONG_TAPS, ELM_GESTURE_STATE_MOVE, onLongTapMove, this);
108 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_LONG_TAPS, ELM_GESTURE_STATE_END, onLongTapEnd, this);
109 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_LONG_TAPS, ELM_GESTURE_STATE_ABORT, onLongTapEnd, this);
110 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_N_DOUBLE_TAPS, ELM_GESTURE_STATE_END, onDoubleTapEnd, this);
112 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_START, onMomentumStart, this);
113 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_MOVE, onMomentumMove, this);
114 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_END, onMomentumEnd, this);
115 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_ABORT, onMomentumAbort, this);
116 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_START, onZoomStart, this);
118 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_MOVE, onZoomMove, this);
119 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_END, onZoomEnd, this);
120 elm_gesture_layer_cb_set(m_gestureObject, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_ABORT, onZoomEnd, this);
122 // add evas callbacks.
123 evas_object_event_callback_add(m_viewWidget, EVAS_CALLBACK_MOUSE_UP, onMouseUp, this);
125 #if ENABLE(TIZEN_DESKTOP_BROWSING)
126 evas_object_event_callback_add(m_viewWidget, EVAS_CALLBACK_MOUSE_MOVE, onMouseMove, this);
127 evas_object_event_callback_add(m_viewWidget, EVAS_CALLBACK_MOUSE_DOWN, onMouseDown, this);
131 Evas_Event_Flags GestureRecognizer::onTapStart(void* data, void* eventInfo)
133 static_cast<GestureRecognizer*>(data)->startTap(static_cast<Elm_Gesture_Taps_Info*>(eventInfo));
134 return EVAS_EVENT_FLAG_NONE;
137 Evas_Event_Flags GestureRecognizer::onTapEnd(void* data, void* eventInfo)
139 static_cast<GestureRecognizer*>(data)->endTap(static_cast<Elm_Gesture_Taps_Info*>(eventInfo));
140 return EVAS_EVENT_FLAG_NONE;
143 Evas_Event_Flags GestureRecognizer::onTapAbort(void* data, void* eventInfo)
145 static_cast<GestureRecognizer*>(data)->abortTap(static_cast<Elm_Gesture_Taps_Info*>(eventInfo));
146 return EVAS_EVENT_FLAG_NONE;
149 Evas_Event_Flags GestureRecognizer::onLongTapStart(void* data, void* eventInfo)
151 static_cast<GestureRecognizer*>(data)->startLongTap(static_cast<Elm_Gesture_Taps_Info*>(eventInfo));
152 return EVAS_EVENT_FLAG_NONE;
155 Evas_Event_Flags GestureRecognizer::onLongTapMove(void* data, void* eventInfo)
157 static_cast<GestureRecognizer*>(data)->moveLongTap(static_cast<Elm_Gesture_Taps_Info*>(eventInfo));
158 return EVAS_EVENT_FLAG_NONE;
161 Evas_Event_Flags GestureRecognizer::onLongTapEnd(void* data, void* eventInfo)
163 static_cast<GestureRecognizer*>(data)->endLongTap(static_cast<Elm_Gesture_Taps_Info*>(eventInfo));
164 return EVAS_EVENT_FLAG_NONE;
167 Evas_Event_Flags GestureRecognizer::onDoubleTapEnd(void* data, void* eventInfo)
169 static_cast<GestureRecognizer*>(data)->endDoubleTap(static_cast<Elm_Gesture_Taps_Info*>(eventInfo));
170 return EVAS_EVENT_FLAG_NONE;
173 Evas_Event_Flags GestureRecognizer::onMomentumStart(void* data, void* eventInfo)
175 static_cast<GestureRecognizer*>(data)->startMomentum(static_cast<Elm_Gesture_Momentum_Info*>(eventInfo));
176 return EVAS_EVENT_FLAG_NONE;
179 Evas_Event_Flags GestureRecognizer::onMomentumMove(void* data, void* eventInfo)
181 static_cast<GestureRecognizer*>(data)->moveMomentum(static_cast<Elm_Gesture_Momentum_Info*>(eventInfo));
182 return EVAS_EVENT_FLAG_NONE;
185 Evas_Event_Flags GestureRecognizer::onMomentumEnd(void* data, void* eventInfo)
187 static_cast<GestureRecognizer*>(data)->endMomentum(static_cast<Elm_Gesture_Momentum_Info*>(eventInfo));
188 return EVAS_EVENT_FLAG_NONE;
191 Evas_Event_Flags GestureRecognizer::onMomentumAbort(void* data, void* eventInfo)
193 Elm_Gesture_Momentum_Info* event = static_cast<Elm_Gesture_Momentum_Info*>(eventInfo);
194 // Set momentum value to 0 because momentum is aborted.
197 static_cast<GestureRecognizer*>(data)->endMomentum(event);
198 return EVAS_EVENT_FLAG_NONE;
201 Evas_Event_Flags GestureRecognizer::onZoomStart(void* data, void* eventInfo)
203 static_cast<GestureRecognizer*>(data)->startZoom(static_cast<Elm_Gesture_Zoom_Info*>(eventInfo));
204 return EVAS_EVENT_FLAG_NONE;
207 void GestureRecognizer::onMouseUp(void* data, Evas*, Evas_Object* ewkView, void* eventInfo)
209 Evas_Event_Mouse_Up* event = static_cast<Evas_Event_Mouse_Up*>(eventInfo);
210 static_cast<GestureRecognizer*>(data)->processScheduledTap(event->canvas.x, event->canvas.y, event->timestamp);
212 #if ENABLE(TIZEN_DESKTOP_BROWSING)
213 Ewk_View_Smart_Data* smartData = 0;
214 smartData = (Ewk_View_Smart_Data*)evas_object_smart_data_get(ewkView);
215 EwkViewImpl* impl = smartData->priv;
217 impl->page()->handleMouseEvent(NativeWebMouseEvent(event, impl->transformFromScene(), impl->transformToScreen()));
221 #if ENABLE(TIZEN_DESKTOP_BROWSING)
222 void GestureRecognizer::onMouseDown(void* data, Evas*, Evas_Object* ewkView, void* eventInfo)
224 Evas_Event_Mouse_Down* event = static_cast<Evas_Event_Mouse_Down*>(eventInfo);
226 Ewk_View_Smart_Data* smartData = 0;
227 smartData = (Ewk_View_Smart_Data*)evas_object_smart_data_get(ewkView);
228 EwkViewImpl* impl = smartData->priv;
230 impl->page()->handleMouseEvent(NativeWebMouseEvent(event, impl->transformFromScene(), impl->transformToScreen()));
234 void GestureRecognizer::onMouseMove(void* data, Evas*, Evas_Object* ewkView, void* eventInfo)
236 Evas_Event_Mouse_Move* event = static_cast<Evas_Event_Mouse_Move*>(eventInfo);
238 Ewk_View_Smart_Data* smartData = 0;
239 smartData = (Ewk_View_Smart_Data*)evas_object_smart_data_get(ewkView);
240 EwkViewImpl* impl = smartData->priv;
242 impl->page()->handleMouseEvent(NativeWebMouseEvent(event, impl->transformFromScene(), impl->transformToScreen()));
246 void GestureRecognizer::startTap(Elm_Gesture_Taps_Info* event)
248 m_currentPoint = m_pressedPoint = IntPoint(event->x, event->y);
250 setTapScheduled(false);
251 m_isLongTapProcessed = false;
252 startGesture(EWK_GESTURE_TAP, IntPoint(event->x, event->y), IntPoint(), 1, 1);
255 void GestureRecognizer::endTap(Elm_Gesture_Taps_Info* event)
260 m_currentPoint = IntPoint(event->x, event->y);
261 processTap(event->x, event->y, event->timestamp);
264 void GestureRecognizer::abortTap(Elm_Gesture_Taps_Info* event)
266 // The elm_gesture_layer aborts tap when 0.4 second is passed, but we want to process tap after 0.4 second.
267 // So, I set isTapScheduled to true to process tap when mouse up.
268 if (event->n == 1) // Tap is aborted after 0.4 second.
269 setTapScheduled(true);
270 else // Tap is aborted by moving before 0.4 second.
271 setTapScheduled(false);
274 void GestureRecognizer::processTap(int x, int y, unsigned int timestamp)
276 endGesture(EWK_GESTURE_TAP, IntPoint(x, y), IntPoint(), 1, 1);
277 setTapScheduled(false);
280 void GestureRecognizer::processScheduledTap(int x, int y, unsigned int timestamp)
282 if (m_isTapScheduled)
283 processTap(x, y, timestamp);
286 void GestureRecognizer::startLongTap(Elm_Gesture_Taps_Info* event)
291 void GestureRecognizer::moveLongTap(Elm_Gesture_Taps_Info* event)
295 // We have to process only first movement as a long tap.
296 if (m_longTapCount != 1 || event->n != 1)
299 setTapScheduled(false);
301 startGesture(EWK_GESTURE_LONG_PRESS, IntPoint(event->x, event->y), IntPoint(), 1, 1);
302 m_isLongTapProcessed = true;
305 void GestureRecognizer::endLongTap(Elm_Gesture_Taps_Info* event)
307 if (event->n != 1 || !m_isLongTapProcessed)
310 endGesture(EWK_GESTURE_LONG_PRESS, IntPoint(event->x, event->y), IntPoint(), 1, 1);
313 void GestureRecognizer::endDoubleTap(Elm_Gesture_Taps_Info* event)
318 // We do not process tap after double tap occurs.
319 setTapScheduled(false);
321 endGesture(EWK_GESTURE_TAP, IntPoint(event->x, event->y), IntPoint(), 1, 2);
324 // The isTapScheduled will be set to true when tap is aborted,
325 // and set to false when zoom, pan, double tap and long tap is occured.
326 // Additionally, focus will be set when focus timer is expired,
327 // and will be clear when tap is processed or we don't want to process scheduled tap.
328 void GestureRecognizer::setTapScheduled(bool scheduled)
330 m_isTapScheduled = scheduled;
333 void GestureRecognizer::startMomentum(Elm_Gesture_Momentum_Info* event)
338 startGesture(EWK_GESTURE_PAN, IntPoint(event->x2, event->y2), IntPoint(), 1, 1);
341 void GestureRecognizer::moveMomentum(Elm_Gesture_Momentum_Info* event)
346 m_currentPoint = IntPoint(event->x2, event->y2);
348 if (m_isTapScheduled && (getPointDistanceSquare(m_pressedPoint, m_currentPoint) > s_tapThreshold))
349 setTapScheduled(false);
351 moveGesture(EWK_GESTURE_PAN, m_currentPoint, IntPoint(event->mx, event->my), 1, 1);
354 void GestureRecognizer::endMomentum(Elm_Gesture_Momentum_Info* event)
356 endGesture(EWK_GESTURE_PAN, IntPoint(event->x2, event->y2), IntPoint(event->mx, event->my), 1, 1);
360 startGesture(EWK_GESTURE_FLICK, IntPoint(event->x2, event->y2), IntPoint(event->mx, event->my), 1, 1);
363 void GestureRecognizer::startZoom(Elm_Gesture_Zoom_Info* event)
365 setTapScheduled(false);
366 startGesture(EWK_GESTURE_PINCH, IntPoint(event->x, event->y), IntPoint(), event->zoom, 1);
369 Evas_Event_Flags GestureRecognizer::onZoomMove(void* data, void* eventInfo)
371 static_cast<GestureRecognizer*>(data)->moveZoom(static_cast<Elm_Gesture_Zoom_Info*>(eventInfo));
372 return EVAS_EVENT_FLAG_NONE;
375 Evas_Event_Flags GestureRecognizer::onZoomEnd(void* data, void* eventInfo)
377 static_cast<GestureRecognizer*>(data)->endZoom(static_cast<Elm_Gesture_Zoom_Info*>(eventInfo));
378 return EVAS_EVENT_FLAG_NONE;
381 void GestureRecognizer::moveZoom(Elm_Gesture_Zoom_Info* event)
383 moveGesture(EWK_GESTURE_PINCH, IntPoint(event->x, event->y), IntPoint(), event->zoom, 1);
386 void GestureRecognizer::endZoom(Elm_Gesture_Zoom_Info* event)
388 endGesture(EWK_GESTURE_PINCH, IntPoint(event->x, event->y), IntPoint(), event->zoom, 1);
391 void GestureRecognizer::startGesture(Ewk_Gesture_Type type, const IntPoint& position, const IntPoint& velocity, double scale, int count)
393 const Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(m_viewWidget));
394 EINA_SAFETY_ON_NULL_RETURN(smartData->api);
395 EINA_SAFETY_ON_NULL_RETURN(smartData->api->gesture_start);
397 Ewk_Event_Gesture gestureEvent;
398 memset(&gestureEvent, 0, sizeof(Ewk_Event_Gesture));
399 gestureEvent.type = type;
400 gestureEvent.position.x = position.x();
401 gestureEvent.position.y = position.y();
402 gestureEvent.velocity.x = velocity.x();
403 gestureEvent.velocity.y = velocity.y();
404 gestureEvent.scale = scale;
405 gestureEvent.count = count;
406 gestureEvent.timestamp = ecore_time_get() * 1000;
408 smartData->api->gesture_start(const_cast<Ewk_View_Smart_Data*>(smartData), &gestureEvent);
411 void GestureRecognizer::endGesture(Ewk_Gesture_Type type, const IntPoint& position, const IntPoint& velocity, double scale, int count)
413 const Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(m_viewWidget));
414 EINA_SAFETY_ON_NULL_RETURN(smartData->api);
415 EINA_SAFETY_ON_NULL_RETURN(smartData->api->gesture_end);
417 Ewk_Event_Gesture gestureEvent;
418 memset(&gestureEvent, 0, sizeof(Ewk_Event_Gesture));
419 gestureEvent.type = type;
420 gestureEvent.position.x = position.x();
421 gestureEvent.position.y = position.y();
422 gestureEvent.velocity.x = velocity.x();
423 gestureEvent.velocity.y = velocity.y();
424 gestureEvent.scale = scale;
425 gestureEvent.count = count;
426 gestureEvent.timestamp = ecore_time_get() * 1000;
428 smartData->api->gesture_end(const_cast<Ewk_View_Smart_Data*>(smartData), &gestureEvent);
431 void GestureRecognizer::moveGesture(Ewk_Gesture_Type type, const IntPoint& position, const IntPoint& velocity, double scale, int count)
433 const Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(m_viewWidget));
434 EINA_SAFETY_ON_NULL_RETURN(smartData->api);
435 EINA_SAFETY_ON_NULL_RETURN(smartData->api->gesture_move);
437 Ewk_Event_Gesture gestureEvent;
438 memset(&gestureEvent, 0, sizeof(Ewk_Event_Gesture));
439 gestureEvent.type = type;
440 gestureEvent.position.x = position.x();
441 gestureEvent.position.y = position.y();
442 gestureEvent.velocity.x = velocity.x();
443 gestureEvent.velocity.y = velocity.y();
444 gestureEvent.scale = scale;
445 gestureEvent.count = count;
446 gestureEvent.timestamp = ecore_time_get() * 1000;
448 smartData->api->gesture_move(const_cast<Ewk_View_Smart_Data*>(smartData), &gestureEvent);
451 } // namespace WebKit