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 #include <WebCore/IntSize.h>
30 #include <WebCore/IntPoint.h>
32 using namespace WebCore;
36 const double GestureRecognizer::s_thumbscrollMomentumThreshold = 400;
38 static int getPointDistanceSquare(const IntPoint& point1, const IntPoint& point2)
40 int xDistance = point1.x() - point2.x();
41 int yDistance = point1.y() - point2.y();
42 return xDistance * xDistance + yDistance * yDistance;
45 GestureRecognizer::GestureRecognizer(Evas_Object* ewkView)
46 : m_viewWidget(ewkView)
49 , m_isTapScheduled(false)
50 , m_isLongTapProcessed(false)
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();
63 GestureRecognizer::~GestureRecognizer()
66 evas_object_del(m_gestureObject);
68 evas_object_event_callback_del(m_viewWidget, EVAS_CALLBACK_MOUSE_UP, onMouseUp);
71 void GestureRecognizer::initializeCallbacks()
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);
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);
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);
93 // add evas callbacks.
94 evas_object_event_callback_add(m_viewWidget, EVAS_CALLBACK_MOUSE_UP, onMouseUp, this);
97 Evas_Event_Flags GestureRecognizer::onTapStart(void* data, void* eventInfo)
99 static_cast<GestureRecognizer*>(data)->startTap(static_cast<Elm_Gesture_Taps_Info*>(eventInfo));
100 return EVAS_EVENT_FLAG_NONE;
103 Evas_Event_Flags GestureRecognizer::onTapEnd(void* data, void* eventInfo)
105 static_cast<GestureRecognizer*>(data)->endTap(static_cast<Elm_Gesture_Taps_Info*>(eventInfo));
106 return EVAS_EVENT_FLAG_NONE;
109 Evas_Event_Flags GestureRecognizer::onTapAbort(void* data, void* eventInfo)
111 static_cast<GestureRecognizer*>(data)->abortTap(static_cast<Elm_Gesture_Taps_Info*>(eventInfo));
112 return EVAS_EVENT_FLAG_NONE;
115 Evas_Event_Flags GestureRecognizer::onLongTapStart(void* data, void* eventInfo)
117 static_cast<GestureRecognizer*>(data)->startLongTap(static_cast<Elm_Gesture_Taps_Info*>(eventInfo));
118 return EVAS_EVENT_FLAG_NONE;
121 Evas_Event_Flags GestureRecognizer::onLongTapMove(void* data, void* eventInfo)
123 static_cast<GestureRecognizer*>(data)->moveLongTap(static_cast<Elm_Gesture_Taps_Info*>(eventInfo));
124 return EVAS_EVENT_FLAG_NONE;
127 Evas_Event_Flags GestureRecognizer::onLongTapEnd(void* data, void* eventInfo)
129 static_cast<GestureRecognizer*>(data)->endLongTap(static_cast<Elm_Gesture_Taps_Info*>(eventInfo));
130 return EVAS_EVENT_FLAG_NONE;
133 Evas_Event_Flags GestureRecognizer::onDoubleTapEnd(void* data, void* eventInfo)
135 static_cast<GestureRecognizer*>(data)->endDoubleTap(static_cast<Elm_Gesture_Taps_Info*>(eventInfo));
136 return EVAS_EVENT_FLAG_NONE;
139 Evas_Event_Flags GestureRecognizer::onMomentumStart(void* data, void* eventInfo)
141 static_cast<GestureRecognizer*>(data)->startMomentum(static_cast<Elm_Gesture_Momentum_Info*>(eventInfo));
142 return EVAS_EVENT_FLAG_NONE;
145 Evas_Event_Flags GestureRecognizer::onMomentumMove(void* data, void* eventInfo)
147 static_cast<GestureRecognizer*>(data)->moveMomentum(static_cast<Elm_Gesture_Momentum_Info*>(eventInfo));
148 return EVAS_EVENT_FLAG_NONE;
151 Evas_Event_Flags GestureRecognizer::onMomentumEnd(void* data, void* eventInfo)
153 static_cast<GestureRecognizer*>(data)->endMomentum(static_cast<Elm_Gesture_Momentum_Info*>(eventInfo));
154 return EVAS_EVENT_FLAG_NONE;
157 Evas_Event_Flags GestureRecognizer::onMomentumAbort(void* data, void* eventInfo)
159 Elm_Gesture_Momentum_Info* event = static_cast<Elm_Gesture_Momentum_Info*>(eventInfo);
160 // Set momentum value to 0 because momentum is aborted.
163 static_cast<GestureRecognizer*>(data)->endMomentum(event);
164 return EVAS_EVENT_FLAG_NONE;
167 Evas_Event_Flags GestureRecognizer::onZoomStart(void* data, void* eventInfo)
169 static_cast<GestureRecognizer*>(data)->startZoom(static_cast<Elm_Gesture_Zoom_Info*>(eventInfo));
170 return EVAS_EVENT_FLAG_NONE;
173 void GestureRecognizer::onMouseUp(void* data, Evas*, Evas_Object*, void* eventInfo)
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);
179 void GestureRecognizer::startTap(Elm_Gesture_Taps_Info* event)
181 m_currentPoint = m_pressedPoint = IntPoint(event->x, event->y);
183 setTapScheduled(false);
184 m_isLongTapProcessed = false;
185 startGesture(EWK_GESTURE_TAP, IntPoint(event->x, event->y), IntPoint(), 1, 1);
188 void GestureRecognizer::endTap(Elm_Gesture_Taps_Info* event)
193 m_currentPoint = IntPoint(event->x, event->y);
194 processTap(event->x, event->y, event->timestamp);
197 void GestureRecognizer::abortTap(Elm_Gesture_Taps_Info* event)
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);
207 void GestureRecognizer::processTap(int x, int y, unsigned int timestamp)
209 endGesture(EWK_GESTURE_TAP, IntPoint(x, y), IntPoint(), 1, 1);
210 setTapScheduled(false);
213 void GestureRecognizer::processScheduledTap(int x, int y, unsigned int timestamp)
215 if (m_isTapScheduled)
216 processTap(x, y, timestamp);
219 void GestureRecognizer::startLongTap(Elm_Gesture_Taps_Info* event)
224 void GestureRecognizer::moveLongTap(Elm_Gesture_Taps_Info* event)
228 // We have to process only first movement as a long tap.
229 if (m_longTapCount != 1 || event->n != 1)
232 setTapScheduled(false);
234 startGesture(EWK_GESTURE_LONG_PRESS, IntPoint(event->x, event->y), IntPoint(), 1, 1);
235 m_isLongTapProcessed = true;
238 void GestureRecognizer::endLongTap(Elm_Gesture_Taps_Info* event)
240 if (event->n != 1 || !m_isLongTapProcessed)
243 endGesture(EWK_GESTURE_LONG_PRESS, IntPoint(event->x, event->y), IntPoint(), 1, 1);
246 void GestureRecognizer::endDoubleTap(Elm_Gesture_Taps_Info* event)
251 // We do not process tap after double tap occurs.
252 setTapScheduled(false);
254 endGesture(EWK_GESTURE_TAP, IntPoint(event->x, event->y), IntPoint(), 1, 2);
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)
263 m_isTapScheduled = scheduled;
266 void GestureRecognizer::startMomentum(Elm_Gesture_Momentum_Info* event)
271 startGesture(EWK_GESTURE_PAN, IntPoint(event->x2, event->y2), IntPoint(), 1, 1);
274 void GestureRecognizer::moveMomentum(Elm_Gesture_Momentum_Info* event)
279 m_currentPoint = IntPoint(event->x2, event->y2);
281 if (m_isTapScheduled && (getPointDistanceSquare(m_pressedPoint, m_currentPoint) > s_tapThreshold))
282 setTapScheduled(false);
284 moveGesture(EWK_GESTURE_PAN, m_currentPoint, IntPoint(event->mx, event->my), 1, 1);
287 void GestureRecognizer::endMomentum(Elm_Gesture_Momentum_Info* event)
289 endGesture(EWK_GESTURE_PAN, IntPoint(event->x2, event->y2), IntPoint(event->mx, event->my), 1, 1);
293 startGesture(EWK_GESTURE_FLICK, IntPoint(event->x2, event->y2), IntPoint(event->mx, event->my), 1, 1);
296 void GestureRecognizer::startZoom(Elm_Gesture_Zoom_Info* event)
298 setTapScheduled(false);
299 startGesture(EWK_GESTURE_PINCH, IntPoint(event->x, event->y), IntPoint(), event->zoom, 1);
302 Evas_Event_Flags GestureRecognizer::onZoomMove(void* data, void* eventInfo)
304 static_cast<GestureRecognizer*>(data)->moveZoom(static_cast<Elm_Gesture_Zoom_Info*>(eventInfo));
305 return EVAS_EVENT_FLAG_NONE;
308 Evas_Event_Flags GestureRecognizer::onZoomEnd(void* data, void* eventInfo)
310 static_cast<GestureRecognizer*>(data)->endZoom(static_cast<Elm_Gesture_Zoom_Info*>(eventInfo));
311 return EVAS_EVENT_FLAG_NONE;
314 void GestureRecognizer::moveZoom(Elm_Gesture_Zoom_Info* event)
316 moveGesture(EWK_GESTURE_PINCH, IntPoint(event->x, event->y), IntPoint(), event->zoom, 1);
319 void GestureRecognizer::endZoom(Elm_Gesture_Zoom_Info* event)
321 endGesture(EWK_GESTURE_PINCH, IntPoint(event->x, event->y), IntPoint(), event->zoom, 1);
324 void GestureRecognizer::startGesture(Ewk_Gesture_Type type, const IntPoint& position, const IntPoint& velocity, double scale, int count)
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);
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;
341 smartData->api->gesture_start(const_cast<Ewk_View_Smart_Data*>(smartData), &gestureEvent);
344 void GestureRecognizer::endGesture(Ewk_Gesture_Type type, const IntPoint& position, const IntPoint& velocity, double scale, int count)
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);
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;
361 smartData->api->gesture_end(const_cast<Ewk_View_Smart_Data*>(smartData), &gestureEvent);
364 void GestureRecognizer::moveGesture(Ewk_Gesture_Type type, const IntPoint& position, const IntPoint& velocity, double scale, int count)
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);
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;
381 smartData->api->gesture_move(const_cast<Ewk_View_Smart_Data*>(smartData), &gestureEvent);
384 } // namespace WebKit