2 # include "elementary_config.h"
5 #include <Elementary.h>
8 EAPI Eo_Op ELM_OBJ_GESTURE_LAYER_BASE_ID = EO_NOOP;
10 #define MY_CLASS ELM_OBJ_GESTURE_LAYER_CLASS
12 #define MY_CLASS_NAME "elm_gesture_layer"
15 #define ELM_MOUSE_DEVICE 0
16 /* ELM_GESTURE_NEGATIVE_ANGLE - magic number says we didn't compute this yet */
17 #define ELM_GESTURE_NEGATIVE_ANGLE (-1.0) /* Magic number */
18 #define ELM_GESTURE_MOMENTUM_DELAY 25
19 #define ELM_GESTURE_MOMENTUM_TIMEOUT 50
20 #define ELM_GESTURE_MULTI_TIMEOUT 50
21 #define ELM_GESTURE_MINIMUM_MOMENTUM 0.001
23 /* Some Trigo values */
24 #define RAD_90DEG M_PI_2
25 #define RAD_180DEG M_PI
26 #define RAD_270DEG (M_PI_2 * 3)
27 #define RAD_360DEG (M_PI * 2)
29 #define RAD2DEG(x) ((x) * 57.295779513)
30 #define DEG2RAD(x) ((x) / 57.295779513)
33 _glayer_buf_dup(void *buf, size_t size)
43 #define COPY_EVENT_INFO(EV) _glayer_buf_dup(EV, sizeof(*EV))
45 #define SET_TEST_BIT(P) \
47 P->test = P->cbs[ELM_GESTURE_STATE_START] || \
48 P->cbs[ELM_GESTURE_STATE_MOVE] || \
49 P->cbs[ELM_GESTURE_STATE_END] || \
50 P->cbs[ELM_GESTURE_STATE_ABORT]; \
53 #define IS_TESTED_GESTURE(gesture) \
54 ((gesture) ? (gesture)->test : EINA_FALSE)
56 #define IS_TESTED(T) \
57 ((sd->gesture[T]) ? sd->gesture[T]->test : EINA_FALSE)
59 #define ELM_GESTURE_LAYER_DATA_GET(o, sd) \
60 Elm_Gesture_Layer_Smart_Data * sd = eo_data_scope_get(o, MY_CLASS)
62 #define ELM_GESTURE_LAYER_DATA_GET_OR_RETURN(o, ptr) \
63 ELM_GESTURE_LAYER_DATA_GET(o, ptr); \
66 CRITICAL("No widget data for object %p (%s)", \
67 o, evas_object_type_get(o)); \
71 #define ELM_GESTURE_LAYER_DATA_GET_OR_RETURN_VAL(o, ptr, val) \
72 ELM_GESTURE_LAYER_DATA_GET(o, ptr); \
75 CRITICAL("No widget data for object %p (%s)", \
76 o, evas_object_type_get(o)); \
80 #define ELM_GESTURE_LAYER_CHECK(obj) \
81 if (!obj || !eo_isa(obj, MY_CLASS)) \
87 * @struct _Pointer_Event
88 * Struct holds pointer-event info
89 * This is a generic pointer event structure
91 * @ingroup Elm_Gesture_Layer
96 unsigned int timestamp;
98 Evas_Callback_Type event_type;
104 * @typedef Pointer_Event
105 * Type for generic pointer event structure
107 * @ingroup Elm_Gesture_Layer
109 typedef struct _Pointer_Event Pointer_Event;
115 * Struct holds callback information.
117 * @ingroup Elm_Gesture_Layer
122 void *user_data; /**< Holds user data to CB (like sd) */
123 Elm_Gesture_Event_Cb cb;
130 * type for callback information
132 * @ingroup Elm_Gesture_Layer
134 typedef struct _Func_Data Func_Data;
139 * @struct _Gesture_Info
140 * Struct holds gesture info
142 * @ingroup Elm_Gesture_Layer
147 void *data; /**< Holds gesture intemidiate processing data */
148 Eina_Inlist *cbs[ELM_GESTURE_STATE_ABORT + 1]; /**< Callback info (Func_Data) for states */
149 Elm_Gesture_Type g_type; /**< gesture type */
150 Elm_Gesture_State state; /**< gesture state */
151 void *info; /**< Data for the state callback */
152 Eina_Bool test; /**< if true this gesture should be tested on input */
158 * @typedef Gesture_Info
159 * Type for _Gesture_Info
161 * @ingroup Elm_Gesture_Layer
163 typedef struct _Gesture_Info Gesture_Info;
167 void (*test)(Evas_Object *obj, Pointer_Event *pe,
168 void *event_info, Evas_Callback_Type event_type,
169 Elm_Gesture_Type g_type);
170 void (*reset)(Gesture_Info *gesture);
171 void (*cont_reset)(Gesture_Info *gesture); /* Can be NULL. */
174 /* functions referred by _glayer_tests_array */
175 static void _tap_gesture_test(Evas_Object *obj,
178 Evas_Callback_Type event_type,
179 Elm_Gesture_Type g_type);
180 static void _tap_gestures_test_reset(Gesture_Info *gesture);
181 static void _n_long_tap_test(Evas_Object *obj,
184 Evas_Callback_Type event_type,
185 Elm_Gesture_Type g_type);
186 static void _n_long_tap_test_reset(Gesture_Info *gesture);
187 static void _momentum_test(Evas_Object *obj,
190 Evas_Callback_Type event_type,
191 Elm_Gesture_Type g_type);
192 static void _momentum_test_reset(Gesture_Info *gesture);
193 static void _n_line_test(Evas_Object *obj,
196 Evas_Callback_Type event_type,
197 Elm_Gesture_Type g_type);
198 static void _line_test_reset(Gesture_Info *gesture);
199 static void _zoom_test(Evas_Object *obj,
202 Evas_Callback_Type event_type,
203 Elm_Gesture_Type g_type);
204 static void _zoom_test_reset(Gesture_Info *gesture);
205 static void _rotate_test(Evas_Object *obj,
208 Evas_Callback_Type event_type,
209 Elm_Gesture_Type g_type);
210 static void _rotate_test_reset(Gesture_Info *gesture);
212 static void _event_process(void *data,
215 Evas_Callback_Type event_type);
217 static void _callbacks_unregister(Evas_Object *obj);
219 /* Should be the same order as _Elm_Gesture_Type */
220 static Tests_Array_Funcs _glayer_tests_array[] = {
221 { NULL, NULL, NULL }, /** Because someone made an awful mistake. */
222 { _tap_gesture_test, _tap_gestures_test_reset, NULL },
223 /* ELM_GESTURE_N_TAPS */
224 { _n_long_tap_test, _n_long_tap_test_reset, NULL },
225 /* ELM_GESTURE_N_LONG_TAPS */
226 { _tap_gesture_test, _tap_gestures_test_reset, NULL },
227 /* ELM_GESTURE_N_DOUBLE_TAPS */
228 { _tap_gesture_test, _tap_gestures_test_reset, NULL },
229 /* ELM_GESTURE_N_TRIPLE_TAPS */
230 { _momentum_test, _momentum_test_reset, _momentum_test_reset },
231 /* ELM_GESTURE_MOMENTUM */
232 { _n_line_test, _line_test_reset, _line_test_reset },
233 /* ELM_GESTURE_N_LINES */
234 { _n_line_test, _line_test_reset, _line_test_reset },
235 /* ELM_GESTURE_N_FLICKS */
236 { _zoom_test, _zoom_test_reset, _zoom_test_reset },
237 /* ELM_GESTURE_ZOOM */
238 { _rotate_test, _rotate_test_reset, _rotate_test_reset },
239 /* ELM_GESTURE_ROTATE */
246 * @struct _Event_History
247 * Struct holds event history.
248 * These events are repeated if no gesture found.
250 * @ingroup Elm_Gesture_Layer
252 struct _Event_History
256 Evas_Callback_Type event_type;
262 * @typedef Event_History
263 * Type for _Event_History
265 * @ingroup Elm_Gesture_Layer
267 typedef struct _Event_History Event_History;
269 /* All *Type structs hold result for the user in 'info' field
270 * The rest is gesture processing intermediate data.
271 * NOTE: info field must be FIRST in the struct.
272 * This is used when reporting ABORT in _event_history_clear() */
275 Elm_Gesture_Taps_Info info;
278 unsigned int n_taps_needed;
282 typedef struct _Taps_Type Taps_Type;
284 struct _Long_Tap_Type
286 Elm_Gesture_Taps_Info info;
289 Ecore_Timer *timeout; /* When this expires, long tap STARTed */
292 typedef struct _Long_Tap_Type Long_Tap_Type;
294 struct _Momentum_Type /* Fields used by _line_test() */
296 Elm_Gesture_Momentum_Info info;
297 Evas_Coord_Point line_st;
298 Evas_Coord_Point line_end;
299 unsigned int t_st_x; /* Time start on X */
300 unsigned int t_st_y; /* Time start on Y */
301 unsigned int t_end; /* Time end */
302 unsigned int t_up; /* Recent up event time */
305 typedef struct _Momentum_Type Momentum_Type;
309 Evas_Coord_Point line_st;
310 Evas_Coord_Point line_end;
311 Evas_Coord line_length;
312 unsigned int t_st; /* Time start */
313 unsigned int t_end; /* Time end */
315 double line_angle; /* Current angle of line */
317 typedef struct _Line_Data Line_Data;
319 struct _Line_Type /* Fields used by _line_test() */
321 Elm_Gesture_Line_Info info;
322 Eina_List *list; /* List of Line_Data */
324 typedef struct _Line_Type Line_Type;
326 struct _Zoom_Type /* Fields used by _zoom_test() */
328 Elm_Gesture_Zoom_Info info;
329 Pointer_Event zoom_st;
330 Pointer_Event zoom_mv;
331 Pointer_Event zoom_st1;
332 Pointer_Event zoom_mv1;
333 Evas_Event_Mouse_Wheel *zoom_wheel;
334 Evas_Coord zoom_base; /* Holds gap between fingers on
336 Evas_Coord zoom_distance_tolerance;
337 unsigned int m_st_tm; /* momentum start time */
338 unsigned int m_prev_tm; /* momentum prev time */
339 int dir; /* Direction: 1=zoom-in, (-1)=zoom-out */
340 double m_base; /* zoom value when momentum starts */
343 typedef struct _Zoom_Type Zoom_Type;
345 struct _Rotate_Type /* Fields used by _rotation_test() */
347 Elm_Gesture_Rotate_Info info;
348 Pointer_Event rotate_st;
349 Pointer_Event rotate_mv;
350 Pointer_Event rotate_st1;
351 Pointer_Event rotate_mv1;
352 unsigned int prev_momentum_tm; /* timestamp of prev_momentum */
353 double prev_momentum; /* Snapshot of momentum 0.01
355 double accum_momentum;
356 double rotate_angular_tolerance;
359 typedef struct _Rotate_Type Rotate_Type;
361 typedef struct _Elm_Gesture_Layer_Smart_Data Elm_Gesture_Layer_Smart_Data;
362 struct _Elm_Gesture_Layer_Smart_Data
364 Evas_Object *target; /* Target Widget */
365 Event_History *event_history_list;
368 Evas_Coord zoom_distance_tolerance;
369 Evas_Coord line_distance_tolerance;
370 double line_angular_tolerance;
371 double zoom_wheel_factor; /* mouse wheel zoom steps */
372 double zoom_finger_factor; /* used for zoom factor */
373 double rotate_angular_tolerance;
374 unsigned int flick_time_limit_ms;
375 double long_tap_start_timeout;
376 Eina_Bool glayer_continues_enable;
377 double double_tap_timeout;
382 Gesture_Info *gesture[ELM_GESTURE_LAST];
383 Eina_List *pending; /* List of devices need to refeed
385 Eina_List *touched; /* Information of touched devices */
388 Evas_Coord tap_finger_size; /* Default from Config */
389 Ecore_Timer *gest_taps_timeout; /* When this expires, dbl
390 * click/taps ABORTed */
392 Eina_Bool repeat_events : 1;
395 /* START - Functions to manage touched-device list */
398 * This function is used to find if device is touched
400 * @ingroup Elm_Gesture_Layer
403 _device_compare(const void *data1,
406 /* Compare the two device numbers */
407 return ((Pointer_Event *)data1)->device - ((Pointer_Event *)data2)->device;
413 * Remove Pointer Event from touched device list
414 * @param list Pointer to touched device list.
415 * @param Pointer_Event Pointer to PE.
417 * @ingroup Elm_Gesture_Layer
420 _touched_device_remove(Eina_List *list,
423 Eina_List *lst = NULL;
424 Pointer_Event *p = eina_list_search_unsorted(list, _device_compare, pe);
427 lst = eina_list_remove(list, p);
438 * Recoed Pointer Event in touched device list
439 * Note: This fuction allocates memory for PE event
440 * This memory is released in _touched_device_remove()
441 * @param list Pointer to touched device list.
442 * @param Pointer_Event Pointer to PE.
444 * @ingroup Elm_Gesture_Layer
447 _touched_device_add(Eina_List *list,
450 Pointer_Event *p = eina_list_search_unsorted(list, _device_compare, pe);
452 if (p) /* We like to track device touch-position, overwrite info */
454 memcpy(p, pe, sizeof(Pointer_Event));
458 if ((pe->event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
459 (pe->event_type == EVAS_CALLBACK_MULTI_DOWN)) /* Add touched
463 p = malloc(sizeof(Pointer_Event));
464 /* Freed in _touched_device_remove() */
465 memcpy(p, pe, sizeof(Pointer_Event));
466 return eina_list_append(list, p);
472 /* END - Functions to manage touched-device list */
478 * @param event_info pointer to event.
480 * @ingroup Elm_Gesture_Layer
482 static Evas_Event_Flags
483 _event_flag_get(void *event_info,
484 Evas_Callback_Type event_type)
488 case EVAS_CALLBACK_MOUSE_IN:
489 return ((Evas_Event_Mouse_In *)event_info)->event_flags;
491 case EVAS_CALLBACK_MOUSE_OUT:
492 return ((Evas_Event_Mouse_Out *)event_info)->event_flags;
494 case EVAS_CALLBACK_MOUSE_DOWN:
495 return ((Evas_Event_Mouse_Down *)event_info)->event_flags;
497 case EVAS_CALLBACK_MOUSE_MOVE:
498 return ((Evas_Event_Mouse_Move *)event_info)->event_flags;
500 case EVAS_CALLBACK_MOUSE_UP:
501 return ((Evas_Event_Mouse_Up *)event_info)->event_flags;
503 case EVAS_CALLBACK_MOUSE_WHEEL:
504 return ((Evas_Event_Mouse_Wheel *)event_info)->event_flags;
506 case EVAS_CALLBACK_MULTI_DOWN:
507 return ((Evas_Event_Multi_Down *)event_info)->event_flags;
509 case EVAS_CALLBACK_MULTI_MOVE:
510 return ((Evas_Event_Multi_Move *)event_info)->event_flags;
512 case EVAS_CALLBACK_MULTI_UP:
513 return ((Evas_Event_Multi_Up *)event_info)->event_flags;
515 case EVAS_CALLBACK_KEY_DOWN:
516 return ((Evas_Event_Key_Down *)event_info)->event_flags;
518 case EVAS_CALLBACK_KEY_UP:
519 return ((Evas_Event_Key_Up *)event_info)->event_flags;
522 return EVAS_EVENT_FLAG_NONE;
529 * Sets event flag to value returned from user callback
530 * @param sd Widget Data
531 * @param event_info pointer to event.
532 * @param event_type what type was ev (mouse down, etc...)
533 * @param ev_flags event flags
535 * @ingroup Elm_Gesture_Layer
538 _event_consume(Elm_Gesture_Layer_Smart_Data *sd,
540 Evas_Callback_Type event_type,
541 Evas_Event_Flags ev_flags)
543 /* Mark EVAS_EVENT_FLAG_ON_HOLD on events that are used by gesture layer */
544 /* ev_flags != EVAS_EVENT_FLAG_NONE means target used event and g-layer */
545 /* should not refeed this event. */
547 return; /* This happens when restarting gestures */
549 if (!sd->repeat_events) ev_flags |= EVAS_EVENT_FLAG_ON_HOLD;
555 case EVAS_CALLBACK_MOUSE_DOWN:
556 ((Evas_Event_Mouse_Down *)event_info)->event_flags |= ev_flags;
559 case EVAS_CALLBACK_MOUSE_MOVE:
560 ((Evas_Event_Mouse_Move *)event_info)->event_flags |= ev_flags;
563 case EVAS_CALLBACK_MOUSE_UP:
564 ((Evas_Event_Mouse_Up *)event_info)->event_flags |= ev_flags;
567 case EVAS_CALLBACK_MOUSE_WHEEL:
568 ((Evas_Event_Mouse_Wheel *)event_info)->event_flags |= ev_flags;
571 case EVAS_CALLBACK_MULTI_DOWN:
572 ((Evas_Event_Multi_Down *)event_info)->event_flags |= ev_flags;
575 case EVAS_CALLBACK_MULTI_MOVE:
576 ((Evas_Event_Multi_Move *)event_info)->event_flags |= ev_flags;
579 case EVAS_CALLBACK_MULTI_UP:
580 ((Evas_Event_Multi_Up *)event_info)->event_flags |= ev_flags;
583 case EVAS_CALLBACK_KEY_DOWN:
584 ((Evas_Event_Key_Down *)event_info)->event_flags |= ev_flags;
587 case EVAS_CALLBACK_KEY_UP:
588 ((Evas_Event_Key_Up *)event_info)->event_flags |= ev_flags;
600 * Report current state of a gesture by calling user callback.
601 * @param gesture what gesture state we report.
602 * @param info inforamtion for user callback
604 * @ingroup Elm_Gesture_Layer
606 static Evas_Event_Flags
607 _state_report(Gesture_Info *gesture,
610 Evas_Event_Flags flags = EVAS_EVENT_FLAG_NONE;
611 /* We report current state (START, MOVE, END, ABORT), once */
612 if ((gesture->state != ELM_GESTURE_STATE_UNDEFINED) &&
613 (gesture->cbs[gesture->state])) /* Fill state-info struct and
618 EINA_INLIST_FOREACH(gesture->cbs[gesture->state], cb_info)
619 flags |= cb_info->cb(cb_info->user_data, info);
622 return EVAS_EVENT_FLAG_NONE;
628 * Update state for a given gesture.
629 * We may update gesture state to:
630 * - @c UNDEFINED - current input did not start gesure yet.
631 * - @c START - gesture started according to input.
632 * - @c MOVE - gusture in progress.
633 * - @c END - gesture completed according to input.
634 * - @c ABORT - input does not matches gesure.
635 * note that we may move from UNDEFINED to ABORT
636 * because we may detect that gesture will not START
637 * with a given input.
639 * @param g given gesture to change state.
640 * @param s gesure new state.
641 * @param info buffer to be sent to user callback on report_state.
642 * @param force makes report_state to report the new-state even
643 * if its same as current state. Works for MOVE - gesture in progress.
645 * @ingroup Elm_Gesture_Layer
647 static Evas_Event_Flags
648 _state_set(Gesture_Info *g,
653 Elm_Gesture_State old_state;
655 if ((g->state == s) && (!force))
656 return EVAS_EVENT_FLAG_NONE;
658 old_state = g->state;
661 g->info = info; /* Information for user callback */
662 if ((g->state == ELM_GESTURE_STATE_ABORT) ||
663 (g->state == ELM_GESTURE_STATE_END))
664 g->test = EINA_FALSE;
666 if ((g->state != ELM_GESTURE_STATE_UNDEFINED) &&
667 (!((old_state == ELM_GESTURE_STATE_UNDEFINED) &&
668 (s == ELM_GESTURE_STATE_ABORT))))
669 return _state_report(g, g->info);
671 return EVAS_EVENT_FLAG_NONE;
677 * This resets all gesture states and sets test-bit.
678 * this is used for restarting gestures to listen to input.
679 * happens after we complete a gesture or no gesture was detected.
680 * @param sd Widget data of the gesture-layer object.
682 * @ingroup Elm_Gesture_Layer
685 _states_reset(Elm_Gesture_Layer_Smart_Data *sd)
690 for (i = ELM_GESTURE_FIRST; i < ELM_GESTURE_LAST; i++)
695 _state_set(p, ELM_GESTURE_STATE_UNDEFINED, NULL, EINA_FALSE);
704 * This function is used to save input events in an abstract struct
705 * to be used later by getsure-testing functions.
707 * @param data The gesture-layer object.
708 * @param event_info Pointer to recent input event.
709 * @param event_type Recent input event type.
710 * @param pe The abstract data-struct (output).
712 * @ingroup Elm_Gesture_Layer
715 _pointer_event_make(void *data __UNUSED__,
717 Evas_Callback_Type event_type,
720 memset(pe, '\0', sizeof(*pe));
723 case EVAS_CALLBACK_MOUSE_DOWN:
724 pe->x = ((Evas_Event_Mouse_Down *)event_info)->canvas.x;
725 pe->y = ((Evas_Event_Mouse_Down *)event_info)->canvas.y;
726 pe->timestamp = ((Evas_Event_Mouse_Down *)event_info)->timestamp;
727 pe->device = ELM_MOUSE_DEVICE;
730 case EVAS_CALLBACK_MOUSE_UP:
731 pe->x = ((Evas_Event_Mouse_Up *)event_info)->canvas.x;
732 pe->y = ((Evas_Event_Mouse_Up *)event_info)->canvas.y;
733 pe->timestamp = ((Evas_Event_Mouse_Up *)event_info)->timestamp;
734 pe->device = ELM_MOUSE_DEVICE;
737 case EVAS_CALLBACK_MOUSE_MOVE:
738 pe->x = ((Evas_Event_Mouse_Move *)event_info)->cur.canvas.x;
739 pe->y = ((Evas_Event_Mouse_Move *)event_info)->cur.canvas.y;
740 pe->timestamp = ((Evas_Event_Mouse_Move *)event_info)->timestamp;
741 pe->device = ELM_MOUSE_DEVICE;
744 case EVAS_CALLBACK_MULTI_DOWN:
745 pe->x = ((Evas_Event_Multi_Down *)event_info)->canvas.x;
746 pe->y = ((Evas_Event_Multi_Down *)event_info)->canvas.y;
747 pe->timestamp = ((Evas_Event_Multi_Down *)event_info)->timestamp;
748 pe->device = ((Evas_Event_Multi_Down *)event_info)->device;
751 case EVAS_CALLBACK_MULTI_UP:
752 pe->x = ((Evas_Event_Multi_Up *)event_info)->canvas.x;
753 pe->y = ((Evas_Event_Multi_Up *)event_info)->canvas.y;
754 pe->timestamp = ((Evas_Event_Multi_Up *)event_info)->timestamp;
755 pe->device = ((Evas_Event_Multi_Up *)event_info)->device;
758 case EVAS_CALLBACK_MULTI_MOVE:
759 pe->x = ((Evas_Event_Multi_Move *)event_info)->cur.canvas.x;
760 pe->y = ((Evas_Event_Multi_Move *)event_info)->cur.canvas.y;
761 pe->timestamp = ((Evas_Event_Multi_Move *)event_info)->timestamp;
762 pe->device = ((Evas_Event_Multi_Move *)event_info)->device;
769 pe->event_type = event_type;
776 * This function copies input events.
777 * We copy event info before adding it to history.
778 * The memory is freed when we clear history.
780 * @param event the event to copy
781 * @param event_type event type to copy
783 * @ingroup Elm_Gesture_Layer
786 _event_info_copy(void *event,
787 Evas_Callback_Type event_type)
791 case EVAS_CALLBACK_MOUSE_DOWN:
792 return COPY_EVENT_INFO((Evas_Event_Mouse_Down *)event);
795 case EVAS_CALLBACK_MOUSE_MOVE:
796 return COPY_EVENT_INFO((Evas_Event_Mouse_Move *)event);
799 case EVAS_CALLBACK_MOUSE_UP:
800 return COPY_EVENT_INFO((Evas_Event_Mouse_Up *)event);
803 case EVAS_CALLBACK_MOUSE_WHEEL:
804 return COPY_EVENT_INFO((Evas_Event_Mouse_Wheel *)event);
807 case EVAS_CALLBACK_MULTI_DOWN:
808 return COPY_EVENT_INFO((Evas_Event_Multi_Down *)event);
811 case EVAS_CALLBACK_MULTI_MOVE:
812 return COPY_EVENT_INFO((Evas_Event_Multi_Move *)event);
815 case EVAS_CALLBACK_MULTI_UP:
816 return COPY_EVENT_INFO((Evas_Event_Multi_Up *)event);
819 case EVAS_CALLBACK_KEY_DOWN:
820 return COPY_EVENT_INFO((Evas_Event_Key_Down *)event);
823 case EVAS_CALLBACK_KEY_UP:
824 return COPY_EVENT_INFO((Evas_Event_Key_Up *)event);
833 _event_history_add(Evas_Object *obj,
835 Evas_Callback_Type event_type)
839 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
841 ev = malloc(sizeof(Event_History));
842 ev->event = _event_info_copy(event, event_type); /* Freed on
843 * _event_history_clear */
844 ev->event_type = event_type;
845 sd->event_history_list = (Event_History *)eina_inlist_append(
846 EINA_INLIST_GET(sd->event_history_list), EINA_INLIST_GET(ev));
852 * For all _mouse_* / multi_* functions wethen send this event to
853 * _event_process function.
855 * @param data The gesture-layer object.
856 * @param event_info Pointer to recent input event.
858 * @ingroup Elm_Gesture_Layer
861 _mouse_down_cb(void *data,
863 Evas_Object *obj __UNUSED__,
866 if (((Evas_Event_Mouse_Down *)event_info)->button != 1)
867 return; /* We only process left-click at the moment */
869 _event_process(data, obj, event_info, EVAS_CALLBACK_MOUSE_DOWN);
873 _mouse_move_cb(void *data,
875 Evas_Object *obj __UNUSED__,
878 _event_process(data, obj, event_info, EVAS_CALLBACK_MOUSE_MOVE);
882 _key_down_cb(void *data,
884 Evas_Object *obj __UNUSED__,
887 _event_process(data, obj, event_info, EVAS_CALLBACK_KEY_DOWN);
891 _key_up_cb(void *data,
893 Evas_Object *obj __UNUSED__,
896 _event_process(data, obj, event_info, EVAS_CALLBACK_KEY_UP);
900 _mouse_up_cb(void *data,
902 Evas_Object *obj __UNUSED__,
905 if (((Evas_Event_Mouse_Up *)event_info)->button != 1)
906 return; /* We only process left-click at the moment */
908 _event_process(data, obj, event_info, EVAS_CALLBACK_MOUSE_UP);
912 _mouse_wheel_cb(void *data,
914 Evas_Object *obj __UNUSED__,
917 _event_process(data, obj, event_info, EVAS_CALLBACK_MOUSE_WHEEL);
921 _multi_down_cb(void *data,
923 Evas_Object *obj __UNUSED__,
926 /* Skip the mouse duplicates. */
927 if (((Evas_Event_Multi_Down *) event_info)->device == 0) return;
929 _event_process(data, obj, event_info, EVAS_CALLBACK_MULTI_DOWN);
933 _multi_move_cb(void *data,
935 Evas_Object *obj __UNUSED__,
938 /* Skip the mouse duplicates. */
939 if (((Evas_Event_Multi_Move *) event_info)->device == 0) return;
941 _event_process(data, obj, event_info, EVAS_CALLBACK_MULTI_MOVE);
945 _multi_up_cb(void *data,
947 Evas_Object *obj __UNUSED__,
950 /* Skip the mouse duplicates. */
951 if (((Evas_Event_Multi_Up *) event_info)->device == 0) return;
953 _event_process(data, obj, event_info, EVAS_CALLBACK_MULTI_UP);
957 _target_del_cb(void *data,
959 Evas_Object *obj __UNUSED__,
960 void *event_info __UNUSED__)
962 _callbacks_unregister(data);
963 ELM_GESTURE_LAYER_DATA_GET(data, sd);
970 * We register callbacks when gesture layer is attached to an object
971 * or when its enabled after disable.
973 * @param obj The gesture-layer object.
975 * @ingroup Elm_Gesture_Layer
978 _callbacks_register(Evas_Object *obj)
980 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
982 if (!sd->target) return;
984 evas_object_event_callback_add
985 (sd->target, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, obj);
986 evas_object_event_callback_add
987 (sd->target, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move_cb, obj);
988 evas_object_event_callback_add
989 (sd->target, EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, obj);
991 evas_object_event_callback_add
992 (sd->target, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb, obj);
994 evas_object_event_callback_add
995 (sd->target, EVAS_CALLBACK_MULTI_DOWN, _multi_down_cb, obj);
996 evas_object_event_callback_add
997 (sd->target, EVAS_CALLBACK_MULTI_MOVE, _multi_move_cb, obj);
998 evas_object_event_callback_add
999 (sd->target, EVAS_CALLBACK_MULTI_UP, _multi_up_cb, obj);
1001 evas_object_event_callback_add
1002 (sd->target, EVAS_CALLBACK_KEY_DOWN, _key_down_cb, obj);
1003 evas_object_event_callback_add
1004 (sd->target, EVAS_CALLBACK_KEY_UP, _key_up_cb, obj);
1006 evas_object_event_callback_add
1007 (sd->target, EVAS_CALLBACK_DEL, _target_del_cb, obj);
1013 * We unregister callbacks when gesture layer is disabled.
1015 * @param obj The gesture-layer object.
1017 * @ingroup Elm_Gesture_Layer
1020 _callbacks_unregister(Evas_Object *obj)
1022 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
1024 if (!sd->target) return;
1026 evas_object_event_callback_del_full
1027 (sd->target, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, obj);
1028 evas_object_event_callback_del_full
1029 (sd->target, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move_cb, obj);
1030 evas_object_event_callback_del_full
1031 (sd->target, EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, obj);
1033 evas_object_event_callback_del_full
1034 (sd->target, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb, obj);
1036 evas_object_event_callback_del_full
1037 (sd->target, EVAS_CALLBACK_MULTI_DOWN, _multi_down_cb, obj);
1039 evas_object_event_callback_del_full
1040 (sd->target, EVAS_CALLBACK_MULTI_MOVE, _multi_move_cb, obj);
1042 evas_object_event_callback_del_full
1043 (sd->target, EVAS_CALLBACK_MULTI_UP, _multi_up_cb, obj);
1045 evas_object_event_callback_del_full
1046 (sd->target, EVAS_CALLBACK_KEY_DOWN, _key_down_cb, obj);
1047 evas_object_event_callback_del_full
1048 (sd->target, EVAS_CALLBACK_KEY_UP, _key_up_cb, obj);
1050 evas_object_event_callback_del_full
1051 (sd->target, EVAS_CALLBACK_DEL, _target_del_cb, obj);
1056 * This function is used to find if device number
1057 * is found in a list of devices.
1058 * The list contains devices for refeeding *UP event
1060 * @ingroup Elm_Gesture_Layer
1063 _device_in_pending_cmp(const void *data1,
1066 /* Compare the two device numbers */
1067 return ((intptr_t)data1) - ((intptr_t)data2);
1073 * This functions returns pending-device node
1074 * @ingroup Elm_Gesture_Layer
1077 _device_is_pending(Eina_List *list,
1079 Evas_Callback_Type event_type)
1081 int device = ELM_MOUSE_DEVICE;
1085 case EVAS_CALLBACK_MOUSE_UP:
1088 case EVAS_CALLBACK_MULTI_UP:
1089 device = ((Evas_Event_Multi_Up *)event)->device;
1096 return eina_list_search_unsorted_list
1097 (list, _device_in_pending_cmp, (void *)(intptr_t)device);
1103 * This functions adds device to refeed-pending device list
1104 * @ingroup Elm_Gesture_Layer
1107 _pending_device_add(Eina_List *list,
1109 Evas_Callback_Type event_type)
1111 int device = ELM_MOUSE_DEVICE;
1115 case EVAS_CALLBACK_MOUSE_DOWN:
1118 case EVAS_CALLBACK_MULTI_DOWN:
1119 device = ((Evas_Event_Multi_Down *)event)->device;
1126 if (!eina_list_search_unsorted_list
1127 (list, _device_in_pending_cmp, (void *)(intptr_t)device))
1129 return eina_list_append(list, (void *)(intptr_t)device);
1138 * This function reports ABORT to all none-detected gestures
1139 * Then resets test bits for all desired gesures
1140 * and clears input-events history.
1141 * note: if no gesture was detected, events from history list
1142 * are streamed to the widget because it's unused by layer.
1143 * user may cancel refeed of events by setting repeat events.
1145 * @param obj The gesture-layer object.
1147 * @ingroup Elm_Gesture_Layer
1150 _event_history_clear(Evas_Object *obj)
1154 Evas *e = evas_object_evas_get(obj);
1155 Eina_Bool gesture_found = EINA_FALSE;
1157 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
1159 for (i = ELM_GESTURE_FIRST; i < ELM_GESTURE_LAST; i++)
1164 if (p->state == ELM_GESTURE_STATE_END)
1166 gesture_found = EINA_TRUE;
1169 { /* Report ABORT to all gestures that still not finished */
1171 _state_set(p, ELM_GESTURE_STATE_ABORT,
1172 sd->gesture[i]->info, EINA_FALSE);
1177 _states_reset(sd); /* we are ready to start testing for gestures again */
1179 /* Clear all gestures intermediate data */
1181 /* FIXME: +1 because of the mistake in the enum. */
1182 Gesture_Info **gitr = sd->gesture + 1;
1183 Tests_Array_Funcs *fitr = _glayer_tests_array + 1;
1184 for (; fitr->reset; fitr++, gitr++)
1186 if (IS_TESTED_GESTURE(*gitr))
1191 /* Disable gesture layer so refeeded events won't be consumed by it */
1192 _callbacks_unregister(obj);
1193 while (sd->event_history_list)
1196 t = sd->event_history_list;
1197 Eina_List *pending = _device_is_pending
1198 (sd->pending, sd->event_history_list->event,
1199 sd->event_history_list->event_type);
1201 /* Refeed events if no gesture matched input */
1202 if (pending || ((!gesture_found) && (!sd->repeat_events)))
1204 evas_event_refeed_event(e, sd->event_history_list->event,
1205 sd->event_history_list->event_type);
1209 sd->pending = eina_list_remove_list(sd->pending, pending);
1213 sd->pending = _pending_device_add
1214 (sd->pending, sd->event_history_list->event,
1215 sd->event_history_list->event_type);
1219 free(sd->event_history_list->event);
1220 sd->event_history_list = (Event_History *)eina_inlist_remove(
1221 EINA_INLIST_GET(sd->event_history_list),
1222 EINA_INLIST_GET(sd->event_history_list));
1225 _callbacks_register(obj);
1232 * if gesture was NOT detected AND we only have gestures in ABORT state
1233 * we clear history immediately to be ready for input.
1235 * @param obj The gesture-layer object.
1236 * @return TRUE on event history_clear
1238 * @ingroup Elm_Gesture_Layer
1241 _clear_if_finished(Evas_Object *obj)
1244 Eina_Bool reset_s = EINA_TRUE, all_undefined = EINA_TRUE;
1246 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
1248 /* Clear history if all we have aborted gestures */
1249 for (i = ELM_GESTURE_FIRST; i < ELM_GESTURE_LAST; i++)
1250 { /* If no gesture started and all we have aborted gestures, reset all */
1251 Gesture_Info *p = sd->gesture[i];
1253 if ((p) && (p->state != ELM_GESTURE_STATE_UNDEFINED))
1255 if ((p->state == ELM_GESTURE_STATE_START) ||
1256 (p->state == ELM_GESTURE_STATE_MOVE))
1257 reset_s = EINA_FALSE;
1259 all_undefined = EINA_FALSE;
1263 if (reset_s && (!all_undefined))
1264 return _event_history_clear(obj);
1272 * This function restartes line, flick, zoom and rotate gestures
1273 * when gesture-layer continues-gestures enabled.
1274 * Example of continues-gesture:
1275 * When doing a line, user stops moving finger but keeps fingers on touch.
1276 * This will cause line-end, then as user continues moving his finger
1277 * it re-starts line gesture.
1278 * When continue mode is disabled, user has to lift finger from touch
1279 * to end a gesture. Them touch-again to start a new one.
1281 * @param data The gesture-layer object.
1282 * @param sd gesture layer widget data.
1283 * @param states_reset flag that marks gestures were reset in history clear.
1285 * @ingroup Elm_Gesture_Layer
1288 _continues_gestures_restart(void *data,
1289 Eina_Bool states_reset)
1291 ELM_GESTURE_LAYER_DATA_GET(data, sd);
1293 /* Test all the gestures */
1295 /* FIXME: +1 because of the mistake in the enum. */
1296 Gesture_Info **gitr = sd->gesture + 1;
1297 Tests_Array_Funcs *fitr = _glayer_tests_array + 1;
1298 for (; fitr->test; fitr++, gitr++)
1300 Gesture_Info *g = *gitr;
1301 Eina_Bool tmp = (g) ?
1302 ((states_reset) || ((g->state != ELM_GESTURE_STATE_START)
1303 && (g->state != ELM_GESTURE_STATE_MOVE)))
1305 if (tmp && fitr->cont_reset)
1307 fitr->cont_reset(g);
1308 _state_set(g, ELM_GESTURE_STATE_UNDEFINED, NULL, EINA_FALSE);
1318 * This function the core-function where input handling is done.
1319 * Here we get user input and stream it to gesture testing.
1320 * We notify user about any gestures with new state:
1322 * START - gesture started.
1323 * MOVE - gesture is ongoing.
1324 * END - gesture was completed.
1325 * ABORT - gesture was aborted after START, MOVE (will NOT be completed)
1327 * We also check if a gesture was detected, then reset event history
1328 * If no gestures were found we reset gesture test flag
1329 * after streaming event-history to widget.
1330 * (stream to the widget all events not consumed as a gesture)
1332 * @param data The gesture-layer object.
1333 * @param event_info Pointer to recent input event.
1334 * @param event_type Recent input event type.
1336 * @ingroup Elm_Gesture_Layer
1339 _event_process(void *data,
1340 Evas_Object *obj __UNUSED__,
1342 Evas_Callback_Type event_type)
1345 Pointer_Event *pe = NULL;
1347 ELM_GESTURE_LAYER_DATA_GET(data, sd);
1349 /* Start testing candidate gesture from here */
1350 if (!_pointer_event_make(data, event_info, event_type, &_pe))
1355 /* Test all the gestures */
1357 /* FIXME: +1 because of the mistake in the enum. */
1358 Gesture_Info **gitr = sd->gesture + 1;
1359 Tests_Array_Funcs *fitr = _glayer_tests_array + 1;
1360 for (; fitr->test; fitr++, gitr++)
1362 if (IS_TESTED_GESTURE(*gitr))
1363 fitr->test(data, pe, event_info, event_type, (*gitr)->g_type);
1367 if (_event_flag_get(event_info, event_type) & EVAS_EVENT_FLAG_ON_HOLD)
1368 _event_history_add(data, event_info, event_type);
1370 /* we maintain list of touched devices */
1371 /* We also use move to track current device x.y pos */
1372 if ((event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
1373 (event_type == EVAS_CALLBACK_MULTI_DOWN) ||
1374 (event_type == EVAS_CALLBACK_MOUSE_MOVE) ||
1375 (event_type == EVAS_CALLBACK_MULTI_MOVE))
1377 sd->touched = _touched_device_add(sd->touched, pe);
1379 else if ((event_type == EVAS_CALLBACK_MOUSE_UP) ||
1380 (event_type == EVAS_CALLBACK_MULTI_UP))
1382 sd->touched = _touched_device_remove(sd->touched, pe);
1385 /* Report current states and clear history if needed */
1386 Eina_Bool states_reset = _clear_if_finished(data);
1387 if (sd->glayer_continues_enable)
1388 _continues_gestures_restart(data, states_reset);
1392 _inside(Evas_Coord xx1,
1398 w >>= 1; /* Use half the distance, from center to all directions */
1399 if (!w) /* use system default instead */
1400 w = elm_config_finger_size_get() >> 1; /* Finger size devided by 2 */
1402 if (xx1 < (xx2 - w))
1405 if (xx1 > (xx2 + w))
1408 if (yy1 < (yy2 - w))
1411 if (yy1 > (yy2 + w))
1417 /* All *test_reset() funcs are called to clear
1418 * gesture intermediate data.
1419 * This happens when we need to reset our tests.
1420 * for example when gesture is detected or all ABORTed. */
1422 _tap_gestures_test_reset(Gesture_Info *gesture)
1427 EINA_SAFETY_ON_NULL_RETURN(gesture);
1428 ELM_GESTURE_LAYER_DATA_GET(gesture->obj, sd);
1430 ELM_SAFE_FREE(sd->gest_taps_timeout, ecore_timer_del);
1435 EINA_LIST_FREE(((Taps_Type *)gesture->data)->l, data)
1436 EINA_LIST_FREE(data, pe)
1439 memset(gesture->data, 0, sizeof(Taps_Type));
1442 /* All *test_reset() funcs are called to clear
1443 * gesture intermediate data.
1444 * This happens when we need to reset our tests.
1445 * for example when gesture is detected or all ABORTed. */
1447 _n_long_tap_test_reset(Gesture_Info *gesture)
1452 EINA_SAFETY_ON_NULL_RETURN(gesture);
1453 if (!gesture->data) return;
1457 EINA_LIST_FREE(st->touched, p)
1461 ELM_SAFE_FREE(st->timeout, ecore_timer_del);
1462 memset(gesture->data, 0, sizeof(Long_Tap_Type));
1466 _momentum_test_reset(Gesture_Info *gesture)
1468 EINA_SAFETY_ON_NULL_RETURN(gesture);
1469 if (!gesture->data) return;
1471 memset(gesture->data, 0, sizeof(Momentum_Type));
1475 _line_data_reset(Line_Data *st)
1480 memset(st, 0, sizeof(Line_Data));
1481 st->line_angle = ELM_GESTURE_NEGATIVE_ANGLE;
1485 _line_test_reset(Gesture_Info *gesture)
1490 EINA_SAFETY_ON_NULL_RETURN(gesture);
1491 if (!gesture->data) return;
1495 EINA_LIST_FREE(st->list, t_line)
1501 _zoom_test_reset(Gesture_Info *gesture)
1504 Evas_Modifier_Mask mask;
1506 EINA_SAFETY_ON_NULL_RETURN(gesture);
1507 if (!gesture->data) return;
1508 ELM_GESTURE_LAYER_DATA_GET(gesture->obj, sd);
1511 mask = evas_key_modifier_mask_get(
1512 evas_object_evas_get(sd->target), "Control");
1513 evas_object_key_ungrab(sd->target, "Control_L", mask, 0);
1514 evas_object_key_ungrab(sd->target, "Control_R", mask, 0);
1516 memset(st, 0, sizeof(Zoom_Type));
1517 st->zoom_distance_tolerance = sd->zoom_distance_tolerance;
1518 st->info.zoom = 1.0;
1522 _rotate_test_reset(Gesture_Info *gesture)
1526 EINA_SAFETY_ON_NULL_RETURN(gesture);
1527 if (!gesture->data) return;
1529 ELM_GESTURE_LAYER_DATA_GET(gesture->obj, sd);
1532 memset(st, 0, sizeof(Rotate_Type));
1533 st->info.base_angle = ELM_GESTURE_NEGATIVE_ANGLE;
1534 st->rotate_angular_tolerance = sd->rotate_angular_tolerance;
1538 _match_fingers_compare(Eina_List *list,
1542 /* Compare coords of first item in list to cur coords */
1546 EINA_LIST_FOREACH(list, l, pe_list)
1548 Pointer_Event *pe2 = eina_list_data_get(pe_list);
1550 if (_inside(pe1->x, pe1->y, pe2->x, pe2->y, w))
1558 _pe_device_compare(const void *data1,
1561 /* Compare device of first item in list to our pe device */
1562 const Pointer_Event *pe1 = eina_list_data_get(data1);
1563 const Pointer_Event *pe2 = data2;
1565 if (pe1->device == pe2->device)
1567 else if (pe1->device < pe2->device)
1574 _pointer_event_record(Taps_Type *st,
1577 Elm_Gesture_Layer_Smart_Data *sd,
1579 Evas_Callback_Type event_type)
1581 /* Keep copy of pe and record it in list */
1582 Pointer_Event *p = malloc(sizeof(Pointer_Event));
1584 memcpy(p, pe, sizeof(Pointer_Event));
1585 _event_consume(sd, event_info, event_type, EVAS_EVENT_FLAG_NONE);
1591 /* This will also update middle-point to report to user later */
1592 st->info.x = st->sum_x / st->n_taps;
1593 st->info.y = st->sum_y / st->n_taps;
1594 st->info.timestamp = pe->timestamp;
1598 pe_list = eina_list_append(pe_list, p);
1599 st->l = eina_list_append(st->l, pe_list);
1602 pe_list = eina_list_append(pe_list, p);
1610 * This function computes minimum rect to bound taps at idx index
1612 * @param taps [in] List of lists containing taps info.
1613 * @param idx [in] index of events taken from lists.
1614 * @param r [out] rect object to save info
1615 * @return EINA_TRUE if managed to compute rect.
1617 * @ingroup Elm_Gesture_Layer
1620 _taps_rect_get(Eina_List *taps, int idx, Evas_Coord_Rectangle *r)
1621 { /* Build a rect bounding all taps at index idx */
1623 Evas_Coord bx = 0, by = 0;
1625 Eina_Bool was_init = EINA_FALSE;
1627 EINA_LIST_FOREACH(taps, l, pe_list)
1629 Pointer_Event *pe = eina_list_nth(pe_list, idx);
1630 if (!pe) continue; /* Not suppose to happen */
1634 if (pe->x < r->x) r->x = pe->x;
1635 if (pe->y < r->y) r->y = pe->y;
1636 if (pe->x > bx) bx = pe->x;
1637 if (pe->y > by) by = pe->y;
1643 was_init = EINA_TRUE;
1655 * This function checks if the tap gesture is done.
1657 * @param data gesture info pointer
1658 * @return EINA_TRUE if it is done.
1660 * @ingroup Elm_Gesture_Layer
1663 _tap_gesture_check_finish(Gesture_Info *gesture, Evas_Coord tap_finger_size)
1665 /* Here we check if taps-gesture was completed successfuly */
1666 /* Count how many taps were recieved on each device then */
1667 /* determine if it matches n_taps_needed defined on START */
1669 Taps_Type *st = gesture->data;
1672 Evas_Coord_Rectangle base;
1673 Evas_Coord_Rectangle tmp;
1674 if (!tap_finger_size) /* Use system default if not set by user */
1675 tap_finger_size = elm_config_finger_size_get();
1678 if (!st->l) return EINA_FALSE;
1679 EINA_LIST_FOREACH(st->l, l, pe_list)
1681 /* No match taps number on device, ABORT */
1682 if (eina_list_count(pe_list) != st->n_taps_needed)
1688 /* Now bound each tap touches in a rect, compare diff within tolerance */
1689 /* Get rect based on first DOWN events for all devices */
1690 if (!_taps_rect_get(st->l, 0, &base))
1691 return EINA_FALSE; /* Should not happen */
1693 for(i = 1; i < st->n_taps_needed; i++)
1694 { /* Compare all other rects to base, tolerance is finger size */
1695 if (_taps_rect_get(st->l, i, &tmp))
1697 if (abs(tmp.x - base.x) > tap_finger_size)
1700 if (abs(tmp.y - base.y) > tap_finger_size)
1703 if (abs((tmp.x + tmp.w) - (base.x + base.w)) > tap_finger_size)
1706 if (abs((tmp.y + tmp.h) - (base.y + base.h)) > tap_finger_size)
1717 * This function sets state a tap-gesture to END or ABORT
1719 * @param data gesture info pointer
1721 * @ingroup Elm_Gesture_Layer
1724 _tap_gesture_finish(void *data, Evas_Coord tap_finger_size)
1726 /* This function will test each tap gesture when timer expires */
1727 Elm_Gesture_State s = ELM_GESTURE_STATE_ABORT;
1728 Gesture_Info *gesture = data;
1729 Taps_Type *st = gesture->data;
1731 if (_tap_gesture_check_finish(gesture, tap_finger_size))
1733 s = ELM_GESTURE_STATE_END;
1736 st->info.n = eina_list_count(st->l);
1737 _state_set(gesture, s, gesture->info, EINA_FALSE);
1738 _tap_gestures_test_reset(gesture);
1744 * when this timer expires we finish tap gestures.
1746 * @param data The gesture-layer object.
1747 * @return cancles callback for this timer.
1749 * @ingroup Elm_Gesture_Layer
1752 _multi_tap_timeout(void *data)
1754 ELM_GESTURE_LAYER_DATA_GET(data, sd);
1756 if (IS_TESTED(ELM_GESTURE_N_TAPS))
1757 _tap_gesture_finish(sd->gesture[ELM_GESTURE_N_TAPS],
1758 sd->tap_finger_size);
1760 if (IS_TESTED(ELM_GESTURE_N_DOUBLE_TAPS))
1761 _tap_gesture_finish(sd->gesture[ELM_GESTURE_N_DOUBLE_TAPS],
1762 sd->tap_finger_size);
1764 if (IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS))
1765 _tap_gesture_finish(sd->gesture[ELM_GESTURE_N_TRIPLE_TAPS],
1766 sd->tap_finger_size);
1768 _clear_if_finished(data);
1769 sd->gest_taps_timeout = NULL;
1771 return ECORE_CALLBACK_CANCEL;
1777 * when this timer expires we START long tap gesture
1779 * @param data The gesture-layer object.
1780 * @return cancles callback for this timer.
1782 * @ingroup Elm_Gesture_Layer
1785 _long_tap_timeout(void *data)
1787 Gesture_Info *gesture = data;
1789 _state_set(gesture, ELM_GESTURE_STATE_MOVE,
1790 gesture->data, EINA_TRUE);
1792 return ECORE_CALLBACK_RENEW;
1798 * This function checks the state of a tap gesture.
1800 * @param sd Gesture Layer Widget Data.
1801 * @param pe The recent input event as stored in pe struct.
1802 * @param event_info Original input event pointer.
1803 * @param event_type Type of original input event.
1804 * @param gesture what gesture is tested
1805 * @param how many taps for this gesture (1, 2 or 3)
1807 * @ingroup Elm_Gesture_Layer
1810 _tap_gesture_test(Evas_Object *obj,
1813 Evas_Callback_Type event_type,
1814 Elm_Gesture_Type g_type)
1818 Gesture_Info *gesture;
1819 Eina_List *pe_list = NULL;
1820 Pointer_Event *pe_last = NULL;
1821 Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
1823 /* Here we fill Tap struct */
1824 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
1829 gesture = sd->gesture[g_type];
1830 if (!gesture) return;
1834 case ELM_GESTURE_N_TAPS:
1838 case ELM_GESTURE_N_DOUBLE_TAPS:
1842 case ELM_GESTURE_N_TRIPLE_TAPS:
1852 if (!st) /* Allocated once on first time */
1854 st = calloc(1, sizeof(Taps_Type));
1856 _tap_gestures_test_reset(gesture);
1859 switch (pe->event_type)
1861 case EVAS_CALLBACK_MULTI_DOWN:
1862 case EVAS_CALLBACK_MOUSE_DOWN:
1863 /* Each device taps (DOWN, UP event) registered in same list */
1864 /* Find list for this device or start a new list if not found */
1865 pe_list = eina_list_search_unsorted(st->l, _pe_device_compare, pe);
1867 { /* This device touched before, verify that this tap is on */
1868 /* top of a previous tap (including a tap of other device) */
1869 if (!_match_fingers_compare(st->l, pe, sd->tap_finger_size))
1870 { /* New DOWN event is not on top of any prev touch */
1871 ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
1872 &st->info, EINA_FALSE);
1873 _event_consume(sd, event_info, event_type, ev_flag);
1879 /* All tests are good, register this tap in device list */
1880 pe_list = _pointer_event_record
1881 (st, pe_list, pe, sd, event_info, event_type);
1883 if (!sd->gest_taps_timeout)
1885 if (sd->double_tap_timeout > 0.0)
1887 sd->gest_taps_timeout =
1888 ecore_timer_add(sd->double_tap_timeout,
1889 _multi_tap_timeout, gesture->obj);
1892 else /* We re-allocate gest_taps_timeout between taps */
1893 ecore_timer_reset(sd->gest_taps_timeout);
1895 if ((pe->device == 0) && (eina_list_count(pe_list) == 1))
1896 { /* This is the first mouse down we got */
1897 ev_flag = _state_set(gesture, ELM_GESTURE_STATE_START,
1898 &st->info, EINA_FALSE);
1899 _event_consume(sd, event_info, event_type, ev_flag);
1901 st->n_taps_needed = taps * 2; /* count DOWN and UP */
1905 else if (eina_list_count(pe_list) > st->n_taps_needed)
1906 { /* If we arleady got too many touches for this gesture. */
1907 ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
1908 &st->info, EINA_FALSE);
1911 if (gesture->state == ELM_GESTURE_STATE_MOVE)
1912 { /* Report MOVE if all devices have same DOWN/UP count */
1913 /* Should be in MOVE state from last UP event */
1915 Eina_Bool move = EINA_TRUE;
1918 EINA_LIST_FOREACH(st->l, l, pe_list)
1922 n = eina_list_count(pe_list);
1924 else if (n != eina_list_count(pe_list))
1930 if (move && (n > 0))
1932 ev_flag = _state_set(gesture, ELM_GESTURE_STATE_MOVE,
1933 &st->info, EINA_TRUE);
1939 case EVAS_CALLBACK_MULTI_UP:
1940 case EVAS_CALLBACK_MOUSE_UP:
1941 pe_list = eina_list_search_unsorted(st->l, _pe_device_compare, pe);
1942 if (!pe_list) return;
1944 _pointer_event_record(st, pe_list, pe, sd, event_info, event_type);
1946 if (((gesture->g_type == ELM_GESTURE_N_TAPS) &&
1947 !IS_TESTED(ELM_GESTURE_N_DOUBLE_TAPS) &&
1948 !IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS)) ||
1949 ((gesture->g_type == ELM_GESTURE_N_DOUBLE_TAPS) &&
1950 !IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS)))
1951 { /* Test for finish immidiatly, not waiting for timeout */
1952 if (_tap_gesture_check_finish(gesture, sd->tap_finger_size))
1954 _tap_gesture_finish(gesture, sd->tap_finger_size);
1959 if ((gesture->state == ELM_GESTURE_STATE_START) ||
1960 (gesture->state == ELM_GESTURE_STATE_MOVE))
1961 { /* Tap gesture started, no finger on surface. Report MOVE */
1963 Eina_Bool move = EINA_TRUE;
1966 /* Report move only if all devices have same DOWN/UP count */
1967 EINA_LIST_FOREACH(st->l, l, pe_list)
1971 n = eina_list_count(pe_list);
1973 else if (n != eina_list_count(pe_list))
1979 if ((move && (n > 0)) && (n < st->n_taps_needed))
1980 { /* Set number of fingers and report MOVE */
1981 /* We don't report MOVE when (n >= st->n_taps_needed)
1982 because will be END or ABORT at this stage */
1983 st->info.n = eina_list_count(st->l);
1984 ev_flag = _state_set(gesture, ELM_GESTURE_STATE_MOVE,
1985 &st->info, EINA_TRUE);
1991 case EVAS_CALLBACK_MULTI_MOVE:
1992 case EVAS_CALLBACK_MOUSE_MOVE:
1993 /* Verify that user didn't move out of tap area before next tap */
1994 /* BUT: we need to skip some MOVE events coming before DOWN */
1995 /* when user taps next tap. So fetch LAST recorded event for */
1996 /* device (DOWN or UP event), ignore all MOVEs if last was UP */
1997 pe_last = eina_list_data_get(eina_list_last(
1998 eina_list_search_unsorted(st->l, _pe_device_compare, pe)));
2001 { /* pe_last is the last event recorded for this device */
2002 if ((pe_last->event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
2003 (pe_last->event_type == EVAS_CALLBACK_MULTI_DOWN))
2004 { /* Test only MOVE events that come after DOWN event */
2005 if (!_inside(pe_last->x, pe_last->y, pe->x, pe->y,
2006 sd->tap_finger_size))
2008 ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
2009 &st->info, EINA_FALSE);
2010 _event_consume(sd, event_info, event_type, ev_flag);
2024 * This function computes center-point for long-tap gesture
2026 * @param st Long Tap gesture info pointer
2027 * @param pe The recent input event as stored in pe struct.
2029 * @ingroup Elm_Gesture_Layer
2032 _compute_taps_center(Long_Tap_Type *st,
2039 Evas_Coord x = 0, y = 0;
2041 if (!eina_list_count(st->touched))
2044 EINA_LIST_FOREACH(st->touched, l, p)
2045 { /* Accumulate all then take avarage */
2046 if (p->device == pe->device) /* This will take care of values
2047 * coming from MOVE event */
2059 *x_out = x / eina_list_count(st->touched);
2060 *y_out = y / eina_list_count(st->touched);
2066 * This function checks N long-tap gesture.
2068 * @param obj The gesture-layer object.
2069 * @param pe The recent input event as stored in pe struct.
2070 * @param event_info Original input event pointer.
2071 * @param event_type Type of original input event.
2072 * @param g_type what Gesture we are testing.
2073 * @param taps How many click/taps we test for.
2075 * @ingroup Elm_Gesture_Layer
2078 _n_long_tap_test(Evas_Object *obj,
2081 Evas_Callback_Type event_type,
2082 Elm_Gesture_Type g_type)
2084 Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
2085 Gesture_Info *gesture;
2088 /* Here we fill Recent_Taps struct and fire-up click/tap timers */
2089 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
2091 if (!pe) /* this happens when unhandled event arrived */
2092 return; /* see _make_pointer_event function */
2094 gesture = sd->gesture[g_type];
2095 if (!gesture) return;
2098 if (!st) /* Allocated once on first time */
2100 st = calloc(1, sizeof(Long_Tap_Type));
2102 _n_long_tap_test_reset(gesture);
2105 switch (pe->event_type)
2107 case EVAS_CALLBACK_MULTI_DOWN:
2108 case EVAS_CALLBACK_MOUSE_DOWN:
2109 st->touched = _touched_device_add(st->touched, pe);
2110 st->info.n = eina_list_count(st->touched);
2112 _event_consume(sd, event_info, event_type, ev_flag);
2113 _compute_taps_center(st, &st->info.x, &st->info.y, pe);
2114 st->center_x = st->info.x; /* Update coords for */
2115 st->center_y = st->info.y; /* reporting START */
2117 /* This is the first mouse down we got */
2118 if (eina_list_count(st->touched) == 1)
2120 _state_set(gesture, ELM_GESTURE_STATE_START,
2121 gesture->data, EINA_FALSE);
2122 st->info.timestamp = pe->timestamp;
2124 /* To test long tap */
2125 /* When this timer expires, gesture STARTED */
2126 if ((!st->timeout) && (sd->long_tap_start_timeout > 0.0))
2127 st->timeout = ecore_timer_add(sd->long_tap_start_timeout,
2128 _long_tap_timeout, gesture);
2133 ecore_timer_reset(st->timeout);
2138 case EVAS_CALLBACK_MULTI_UP:
2139 case EVAS_CALLBACK_MOUSE_UP:
2140 st->touched = _touched_device_remove(st->touched, pe);
2141 _compute_taps_center(st, &st->center_x, &st->center_y, pe);
2144 if (gesture->state == ELM_GESTURE_STATE_MOVE)
2145 ev_flag = _state_set(gesture, ELM_GESTURE_STATE_END,
2146 &st->info, EINA_FALSE);
2148 ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
2149 &st->info, EINA_FALSE);
2151 ELM_SAFE_FREE(st->timeout, ecore_timer_del);
2152 _event_consume(sd, event_info, event_type, ev_flag);
2157 case EVAS_CALLBACK_MULTI_MOVE:
2158 case EVAS_CALLBACK_MOUSE_MOVE:
2160 ((gesture->state == ELM_GESTURE_STATE_START) ||
2161 /* Report MOVE only if STARTED */
2162 (gesture->state == ELM_GESTURE_STATE_MOVE)))
2167 _compute_taps_center(st, &x, &y, pe);
2168 /* ABORT if user moved fingers out of tap area */
2169 if (!_inside(x, y, st->center_x, st->center_y,
2170 sd->tap_finger_size))
2172 ELM_SAFE_FREE(st->timeout, ecore_timer_del);
2174 /* Report MOVE if gesture started */
2175 ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
2176 &st->info, EINA_FALSE);
2179 _event_consume(sd, event_info, event_type, ev_flag);
2191 * This function computes momentum for MOMENTUM, LINE and FLICK gestures
2192 * This momentum value will be sent to widget when gesture is completed.
2194 * @param momentum pointer to buffer where we record momentum value.
2195 * @param x1 x coord where user started gesture.
2196 * @param y1 y coord where user started gesture.
2197 * @param x2 x coord where user completed gesture.
2198 * @param y2 y coord where user completed gesture.
2199 * @param t1x timestamp for X, when user started gesture.
2200 * @param t1y timestamp for Y, when user started gesture.
2201 * @param t2 timestamp when user completed gesture.
2203 * @ingroup Elm_Gesture_Layer
2206 _momentum_set(Elm_Gesture_Momentum_Info *momentum,
2215 Evas_Coord velx = 0, vely = 0, vel;
2216 Evas_Coord dx = xx2 - xx1;
2217 Evas_Coord dy = yy2 - yy1;
2222 velx = (dx * 1000) / dtx;
2225 vely = (dy * 1000) / dty;
2227 vel = sqrt((velx * velx) + (vely * vely));
2229 if ((_elm_config->thumbscroll_friction > 0.0) &&
2230 (vel > _elm_config->thumbscroll_momentum_threshold)) /* report
2233 momentum->mx = velx;
2234 momentum->my = vely;
2246 * This function is used for computing rotation angle (DEG).
2248 * @param x1 first finger x location.
2249 * @param y1 first finger y location.
2250 * @param x2 second finger x location.
2251 * @param y2 second finger y location.
2253 * @return angle of the line between (x1,y1), (x2,y2) in Deg.
2254 * Angles now are given in DEG, not RAD.
2255 * ZERO angle at 12-oclock, growing clockwise.
2257 * @ingroup Elm_Gesture_Layer
2260 _angle_get(Evas_Coord xx1,
2265 double a, xx, yy, rt = (-1);
2267 xx = fabs(xx2 - xx1);
2268 yy = fabs(yy2 - yy1);
2270 if (((int)xx) && ((int)yy))
2272 rt = a = RAD2DEG(atan(yy / xx));
2275 if (yy1 < yy2) rt = 360 - a;
2280 if (yy1 < yy2) rt = 180 + a;
2285 if (rt < 0) /* Do this only if rt is not set */
2287 if (((int)xx)) /* Horizontal line */
2289 if (xx2 < xx1) rt = 180;
2293 { /* Vertical line */
2294 if (yy2 < yy1) rt = 90;
2299 /* Now we want to change from:
2301 * original circle 180 0 We want: 270 90
2305 if (rt >= 360) rt -= 360;
2313 * This function is used for computing the magnitude and direction
2314 * of vector between two points.
2316 * @param x1 first finger x location.
2317 * @param y1 first finger y location.
2318 * @param x2 second finger x location.
2319 * @param y2 second finger y location.
2320 * @param l length computed (output)
2321 * @param a angle computed (output)
2323 * @ingroup Elm_Gesture_Layer
2326 _vector_get(Evas_Coord xx1,
2337 *l = (Evas_Coord)sqrt((xx * xx) + (yy * yy));
2338 *a = _angle_get(xx1, yy1, xx2, yy2);
2342 _direction_get(Evas_Coord xx1,
2345 if (xx2 < xx1) return -1;
2346 if (xx2 > xx1) return 1;
2354 * This function tests momentum gesture.
2355 * @param obj The gesture-layer object.
2356 * @param pe The recent input event as stored in pe struct.
2357 * @param event_info recent input event.
2358 * @param event_type recent event type.
2359 * @param g_type what Gesture we are testing.
2361 * @ingroup Elm_Gesture_Layer
2364 _momentum_test(Evas_Object *obj,
2367 Evas_Callback_Type event_type,
2368 Elm_Gesture_Type g_type)
2373 Gesture_Info *gesture;
2374 Pointer_Event pe_local;
2375 Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
2376 Elm_Gesture_State state_to_report = ELM_GESTURE_STATE_MOVE;
2377 unsigned int cnt = 1; /* We start counter counting current pe event */
2379 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
2381 gesture = sd->gesture[g_type];
2382 if (!gesture) return;
2384 /* When continues enable = TRUE a gesture may START on MOVE event */
2385 /* We don't allow this to happen with the if-statement below. */
2386 /* When continues enable = FALSE a gesture may START on DOWN only */
2387 /* Therefor it would NOT start on MOVE event. */
2388 /* NOTE that touched list is updated AFTER this function returns */
2389 /* so (count == 0) when we get here on first touch on surface. */
2390 if ((sd->glayer_continues_enable) && (!eina_list_count(sd->touched)))
2391 return; /* Got move on mouse-over move */
2394 if (!st) /* Allocated once on first time */
2396 st = calloc(1, sizeof(Momentum_Type));
2398 _momentum_test_reset(gesture);
2404 /* First make avarage of all touched devices to determine center point */
2405 pe_local = *pe; /* Copy pe event info to local */
2406 EINA_LIST_FOREACH(sd->touched, l, p)
2407 if (p->device != pe_local.device)
2414 /* Compute avarage to get center point */
2418 /* If user added finger - reset gesture */
2419 if ((st->info.n) && (st->info.n < cnt))
2420 state_to_report = ELM_GESTURE_STATE_ABORT;
2422 if (st->info.n < cnt)
2427 case EVAS_CALLBACK_MOUSE_DOWN:
2428 case EVAS_CALLBACK_MULTI_DOWN:
2429 case EVAS_CALLBACK_MOUSE_MOVE:
2430 case EVAS_CALLBACK_MULTI_MOVE:
2433 if ((event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
2434 (event_type == EVAS_CALLBACK_MULTI_DOWN) ||
2435 (sd->glayer_continues_enable)) /* start also on MOVE */
2436 { /* We start on MOVE when cont-enabled only */
2437 st->line_st.x = st->line_end.x = pe_local.x;
2438 st->line_st.y = st->line_end.y = pe_local.y;
2439 st->t_st_x = st->t_st_y = st->t_end = pe_local.timestamp;
2440 st->xdir = st->ydir = 0;
2441 st->info.x2 = st->info.x1 = pe_local.x;
2442 st->info.y2 = st->info.y1 = pe_local.y;
2443 st->info.tx = st->info.ty = pe_local.timestamp;
2444 ev_flag = _state_set(gesture, ELM_GESTURE_STATE_START,
2445 &st->info, EINA_FALSE);
2446 _event_consume(sd, event_info, event_type, ev_flag);
2454 Eina_Bool force = EINA_TRUE; /* for move state */
2456 /* ABORT if got DOWN or MOVE event after UP+timeout */
2457 if ((st->t_up + ELM_GESTURE_MULTI_TIMEOUT) < pe_local.timestamp)
2459 state_to_report = ELM_GESTURE_STATE_ABORT;
2463 /* We report state but don't compute momentum now */
2464 ev_flag = _state_set(gesture, state_to_report, &st->info,
2466 _event_consume(sd, event_info, event_type, ev_flag);
2467 return; /* Stop computing when user remove finger */
2470 /* Too long of a wait, reset all values */
2471 if ((pe_local.timestamp - ELM_GESTURE_MOMENTUM_TIMEOUT) > st->t_end)
2473 st->line_st.x = pe_local.x;
2474 st->line_st.y = pe_local.y;
2475 st->t_st_y = st->t_st_x = pe_local.timestamp;
2476 st->info.tx = st->t_st_x;
2477 st->info.ty = st->t_st_y;
2478 st->xdir = st->ydir = 0;
2484 xdir = _direction_get(st->line_end.x, pe_local.x);
2485 ydir = _direction_get(st->line_end.y, pe_local.y);
2486 if (xdir && (xdir != st->xdir))
2488 st->line_st.x = st->line_end.x;
2489 st->info.tx = st->t_st_x = st->t_end;
2493 if (ydir && (ydir != st->ydir))
2495 st->line_st.y = st->line_end.y;
2496 st->info.ty = st->t_st_y = st->t_end;
2501 st->info.x2 = st->line_end.x = pe_local.x;
2502 st->info.y2 = st->line_end.y = pe_local.y;
2503 st->t_end = pe_local.timestamp;
2504 _momentum_set(&st->info, st->line_st.x, st->line_st.y,
2505 pe_local.x, pe_local.y, st->t_st_x, st->t_st_y,
2506 pe_local.timestamp);
2508 ev_flag = _state_set(gesture, state_to_report, &st->info,
2510 _event_consume(sd, event_info, event_type, ev_flag);
2513 case EVAS_CALLBACK_MOUSE_UP:
2514 case EVAS_CALLBACK_MULTI_UP:
2515 st->t_up = pe_local.timestamp; /* Record recent up event time */
2516 if ((cnt > 1) || /* Ignore if more fingers touch surface */
2517 (!st->t_st_x)) /* IGNORE if info was cleared, long press,move */
2520 /* Too long of a wait, reset all values */
2521 if ((pe_local.timestamp - ELM_GESTURE_MOMENTUM_TIMEOUT) > st->t_end)
2523 st->line_st.x = pe_local.x;
2524 st->line_st.y = pe_local.y;
2525 st->t_st_y = st->t_st_x = pe_local.timestamp;
2526 st->xdir = st->ydir = 0;
2529 st->info.x2 = pe_local.x;
2530 st->info.y2 = pe_local.y;
2531 st->line_end.x = pe_local.x;
2532 st->line_end.y = pe_local.y;
2533 st->t_end = pe_local.timestamp;
2535 if ((fabs(st->info.mx) > ELM_GESTURE_MINIMUM_MOMENTUM) ||
2536 (fabs(st->info.my) > ELM_GESTURE_MINIMUM_MOMENTUM))
2537 state_to_report = ELM_GESTURE_STATE_END;
2539 state_to_report = ELM_GESTURE_STATE_ABORT;
2541 ev_flag = _state_set(gesture, state_to_report, &st->info,
2543 _event_consume(sd, event_info, event_type, ev_flag);
2552 _line_device_compare(const void *data1,
2555 /* Compare device component of line struct */
2556 const Line_Data *ln1 = data1;
2557 const int *device = data2;
2559 if (ln1->t_st) /* Compare only with lines that started */
2560 return ln1->device - (*device);
2568 * This function construct line struct from input.
2569 * @param info pointer to store line momentum.
2570 * @param st line info to store input data.
2571 * @param pe The recent input event as stored in pe struct.
2573 * @ingroup Elm_Gesture_Layer
2576 _single_line_process(Elm_Gesture_Line_Info *info,
2579 Evas_Callback_Type event_type)
2581 /* Record events and set momentum for line pointed by st */
2587 case EVAS_CALLBACK_MOUSE_DOWN:
2588 case EVAS_CALLBACK_MOUSE_MOVE:
2589 case EVAS_CALLBACK_MULTI_DOWN:
2590 case EVAS_CALLBACK_MULTI_MOVE:
2591 if (!st->t_st) /* This happens only when line starts */
2593 st->line_st.x = pe->x;
2594 st->line_st.y = pe->y;
2595 st->t_st = pe->timestamp;
2596 st->device = pe->device;
2597 info->momentum.x1 = pe->x;
2598 info->momentum.y1 = pe->y;
2599 info->momentum.tx = pe->timestamp;
2600 info->momentum.ty = pe->timestamp;
2607 case EVAS_CALLBACK_MOUSE_UP:
2608 case EVAS_CALLBACK_MULTI_UP:
2609 /* IGNORE if line info was cleared, like long press, move */
2613 st->line_end.x = pe->x;
2614 st->line_end.y = pe->y;
2615 st->t_end = pe->timestamp;
2624 _line_data_reset(st);
2628 info->momentum.x2 = pe->x;
2629 info->momentum.y2 = pe->y;
2630 _momentum_set(&info->momentum, st->line_st.x, st->line_st.y, pe->x, pe->y,
2631 st->t_st, st->t_st, pe->timestamp);
2639 * This function test for (n) line gesture.
2640 * @param obj The gesture-layer object.
2641 * @param pe The recent input event as stored in pe struct.
2642 * @param event_info Original input event pointer.
2643 * @param event_type Type of original input event.
2644 * @param g_type what Gesture we are testing.
2646 * @ingroup Elm_Gesture_Layer
2649 _n_line_test(Evas_Object *obj,
2652 Evas_Callback_Type event_type,
2653 Elm_Gesture_Type g_type)
2658 Gesture_Info *gesture;
2659 Line_Data *line = NULL;
2664 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
2666 gesture = sd->gesture[g_type];
2667 if (!gesture ) return;
2669 /* When continues enable = TRUE a gesture may START on MOVE event */
2670 /* We don't allow this to happen with the if-statement below. */
2671 /* When continues enable = FALSE a gesture may START on DOWN only */
2672 /* Therefor it would NOT start on MOVE event. */
2673 /* NOTE that touched list is updated AFTER this function returns */
2674 /* so (count == 0) when we get here on first touch on surface. */
2675 if ((sd->glayer_continues_enable) && (!eina_list_count(sd->touched)))
2676 return; /* Got move on mouse-over move */
2681 st = calloc(1, sizeof(Line_Type));
2686 cnt = eina_list_count(list);
2688 if (cnt) /* list is not empty, locate this device on list */
2690 line = (Line_Data *)eina_list_search_unsorted
2691 (st->list, _line_device_compare, &pe->device);
2694 if (!line) /* List is empty or device not found, new line-struct on
2697 if ((event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
2698 (event_type == EVAS_CALLBACK_MULTI_DOWN) ||
2699 ((sd->glayer_continues_enable) && /* START on MOVE also */
2700 ((event_type == EVAS_CALLBACK_MOUSE_MOVE) ||
2701 /* Allocate new item on START only */
2702 (event_type == EVAS_CALLBACK_MULTI_MOVE))))
2704 line = calloc(1, sizeof(Line_Data));
2705 _line_data_reset(line);
2706 list = eina_list_append(list, line);
2711 if (!line) /* This may happen on MOVE that comes before DOWN */
2712 return; /* No line-struct to work with, can't continue testing */
2714 /* update st with input */
2715 if (_single_line_process(&st->info, line, pe, event_type))
2716 _event_consume(sd, event_info, event_type, EVAS_EVENT_FLAG_NONE);
2718 /* Get direction and magnitude of the line */
2720 _vector_get(line->line_st.x, line->line_st.y, pe->x, pe->y,
2721 &line->line_length, &angle);
2723 /* These are used later to compare lines length */
2724 Evas_Coord shortest_line_len = line->line_length;
2725 Evas_Coord longest_line_len = line->line_length;
2726 Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
2728 /* Now update line-state */
2729 if (line->t_st) /* Analyze line only if line started */
2731 if (line->line_angle >= 0.0) /* if line direction was set, we
2732 * test if broke tolerance */
2734 double a = fabs(angle - line->line_angle);
2735 /* Distance from line */
2736 double d = (tan(DEG2RAD(a))) * line->line_length;
2737 /* Broke tolerance: abort line and start a new one */
2738 if ((d > sd->line_distance_tolerance) ||
2739 (a > sd->line_angular_tolerance))
2741 ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
2742 &st->info, EINA_FALSE);
2743 _event_consume(sd, event_info, event_type, ev_flag);
2747 /* We may finish line if momentum is zero */
2748 if (sd->glayer_continues_enable)
2750 /* This is for continues-gesture */
2751 /* Finish line on zero momentum for continues gesture */
2752 if ((!st->info.momentum.mx) && (!st->info.momentum.my))
2754 line->line_end.x = pe->x;
2755 line->line_end.y = pe->y;
2756 line->t_end = pe->timestamp;
2761 { /* Record the line angle as it broke minimum length for line */
2762 if (line->line_length >= sd->line_min_length)
2763 st->info.angle = line->line_angle = angle;
2768 if (line->line_angle < 0.0) /* it's not a line, too short
2769 * more close to a tap */
2771 ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
2772 &st->info, EINA_FALSE);
2773 _event_consume(sd, event_info, event_type, ev_flag);
2779 /* Count how many lines already started / ended */
2782 unsigned int tm_start = pe->timestamp;
2783 unsigned int tm_end = pe->timestamp;
2786 double base_angle = ELM_GESTURE_NEGATIVE_ANGLE;
2787 Eina_Bool lines_parallel = EINA_TRUE;
2788 EINA_LIST_FOREACH(list, l, t_line)
2791 base_angle = t_line->line_angle;
2794 if (t_line->line_angle >= 0) /* Compare angle only with
2795 * lines with direction
2798 if (fabs(base_angle - t_line->line_angle) >
2799 sd->line_angular_tolerance)
2800 lines_parallel = EINA_FALSE;
2804 if (t_line->line_length) /* update only if this line is used */
2806 if (shortest_line_len > t_line->line_length)
2807 shortest_line_len = t_line->line_length;
2809 if (longest_line_len < t_line->line_length)
2810 longest_line_len = t_line->line_length;
2816 if (t_line->t_st < tm_start)
2817 tm_start = t_line->t_st;
2823 if (t_line->t_end < tm_end)
2824 tm_end = t_line->t_end;
2828 st->info.momentum.n = started;
2831 ((event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
2832 /* user lift one finger then starts again without line-end - ABORT */
2833 (event_type == EVAS_CALLBACK_MULTI_DOWN)))
2835 ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT, &st->info,
2837 _event_consume(sd, event_info, event_type, ev_flag);
2841 if (!lines_parallel) /* Lines are NOT at same direction, abort this
2844 ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT, &st->info,
2846 _event_consume(sd, event_info, event_type, ev_flag);
2850 /* We report ABORT if lines length are NOT matching when fingers are up */
2851 if ((longest_line_len - shortest_line_len) >
2852 (elm_config_finger_size_get() * 2))
2854 ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT, &st->info,
2856 _event_consume(sd, event_info, event_type, ev_flag);
2860 /* We consider FLICK as a fast line.ABORT if take too long to finish */
2861 if ((g_type == ELM_GESTURE_N_FLICKS) && ((tm_end - tm_start) >
2862 sd->flick_time_limit_ms))
2864 ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT, &st->info,
2866 _event_consume(sd, event_info, event_type, ev_flag);
2872 case EVAS_CALLBACK_MOUSE_UP:
2873 case EVAS_CALLBACK_MULTI_UP:
2874 if ((started) && (started == ended))
2876 ev_flag = _state_set(gesture, ELM_GESTURE_STATE_END,
2877 &st->info, EINA_FALSE);
2878 _event_consume(sd, event_info, event_type, ev_flag);
2883 case EVAS_CALLBACK_MOUSE_DOWN:
2884 case EVAS_CALLBACK_MULTI_DOWN:
2885 case EVAS_CALLBACK_MOUSE_MOVE:
2886 case EVAS_CALLBACK_MULTI_MOVE:
2889 /* For continues gesture */
2890 if (sd->glayer_continues_enable && (started == ended))
2892 ev_flag = _state_set(gesture, ELM_GESTURE_STATE_END,
2893 &st->info, EINA_FALSE);
2894 _event_consume(sd, event_info, event_type, ev_flag);
2897 { /* When continues, may START on MOVE event too */
2898 Elm_Gesture_State s = ELM_GESTURE_STATE_MOVE;
2900 /* This happens when: on n > 1 lines then one finger up */
2901 /* caused abort, then put finger down. */
2902 /* This will stop line from starting again. */
2903 /* Number of lines, MUST match touched-device in list */
2904 if ((!sd->glayer_continues_enable) &&
2905 (eina_list_count(st->list) <
2906 eina_list_count(sd->touched)))
2907 s = ELM_GESTURE_STATE_ABORT;
2909 if (gesture->state == ELM_GESTURE_STATE_UNDEFINED)
2910 s = ELM_GESTURE_STATE_START;
2912 ev_flag = _state_set(gesture, s, &st->info, EINA_TRUE);
2913 _event_consume(sd, event_info, event_type, ev_flag);
2919 return; /* Unhandeld event type */
2926 * This function is used to check if rotation gesture started.
2927 * @param st Contains current rotation values from user input.
2928 * @return TRUE/FALSE if we need to set rotation START.
2930 * @ingroup Elm_Gesture_Layer
2933 _on_rotation_broke_tolerance(Rotate_Type *st)
2935 if (st->info.base_angle < 0)
2936 return EINA_FALSE; /* Angle has to be computed first */
2938 if (st->rotate_angular_tolerance < 0)
2941 double low = st->info.base_angle - st->rotate_angular_tolerance;
2942 double high = st->info.base_angle + st->rotate_angular_tolerance;
2943 double t = st->info.angle;
2967 if ((t < low) || (t > high)) /* This marks that roation action has
2970 st->rotate_angular_tolerance = ELM_GESTURE_NEGATIVE_ANGLE;
2971 st->info.base_angle = st->info.angle; /* Avoid jump in angle value */
2981 * This function is used for computing the gap between fingers.
2982 * It returns the length and center point between fingers.
2984 * @param x1 first finger x location.
2985 * @param y1 first finger y location.
2986 * @param x2 second finger x location.
2987 * @param y2 second finger y location.
2988 * @param x Get center point x cord (output)
2989 * @param y Get center point y cord (output)
2991 * @return length of the line between (x1,y1), (x2,y2) in pixels.
2993 * @ingroup Elm_Gesture_Layer
2996 _finger_gap_length_get(Evas_Coord xx1,
3003 double a, b, xx, yy, gap;
3004 xx = fabs(xx2 - xx1);
3005 yy = fabs(yy2 - yy1);
3006 gap = sqrt((xx * xx) + (yy * yy));
3008 /* START - Compute zoom center point */
3009 /* The triangle defined as follows:
3017 * http://en.wikipedia.org/wiki/Trigonometric_functions
3018 *************************************/
3019 if (((int)xx) && ((int)yy))
3021 double A = atan((yy / xx));
3022 a = (Evas_Coord)((gap / 2) * sin(A));
3023 b = (Evas_Coord)((gap / 2) * cos(A));
3024 *x = (Evas_Coord)((xx2 > xx1) ? (xx1 + b) : (xx2 + b));
3025 *y = (Evas_Coord)((yy2 > yy1) ? (yy1 + a) : (yy2 + a));
3029 if ((int)xx) /* horiz line, take half width */
3031 *x = (Evas_Coord)((xx1 + xx2) / 2);
3032 *y = (Evas_Coord)(yy1);
3035 if ((int)yy) /* vert line, take half width */
3037 *x = (Evas_Coord)(xx1);
3038 *y = (Evas_Coord)((yy1 + yy2) / 2);
3041 /* END - Compute zoom center point */
3043 return (Evas_Coord)gap;
3049 * This function is used for computing zoom value.
3051 * @param st Pointer to zoom data based on user input.
3052 * @param tm_end Recent input event timestamp.
3053 * @param zoom_val Current computed zoom value.
3055 * @return zoom momentum
3057 * @ingroup Elm_Gesture_Layer
3060 _zoom_momentum_get(Zoom_Type *st,
3061 unsigned int tm_end,
3064 unsigned int tm_total;
3065 if (!st->m_st_tm) /* Init, and we don't start computing momentum yet */
3067 st->m_st_tm = st->m_prev_tm = tm_end;
3068 st->m_base = zoom_val;
3072 if ((tm_end - ELM_GESTURE_MOMENTUM_DELAY) < st->m_st_tm)
3073 return 0.0; /* we don't start to compute momentum yet */
3075 if (st->dir) /* if direction was already defined, check if changed */
3077 if (((st->dir < 0) && (zoom_val > st->info.zoom)) ||
3078 /* Direction changed, reset momentum */
3079 ((st->dir > 0) && (zoom_val < st->info.zoom)))
3082 st->dir = (-st->dir);
3087 st->dir = (zoom_val > st->info.zoom) ? 1 : -1; /* init */
3089 if ((tm_end - ELM_GESTURE_MOMENTUM_TIMEOUT) > st->m_prev_tm)
3091 st->m_st_tm = 0; /* Rest momentum when waiting too long */
3095 st->m_prev_tm = tm_end;
3096 tm_total = tm_end - st->m_st_tm;
3099 return ((zoom_val - st->m_base) * 1000) / tm_total;
3107 * This function is used for computing zoom value.
3109 * @param st Pointer to zoom data based on user input.
3110 * @param x1 first finger x location.
3111 * @param y1 first finger y location.
3112 * @param x2 second finger x location.
3113 * @param y2 second finger y location.
3114 * @param factor zoom-factor, used to determine how fast zoom works.
3116 * @return zoom value, when 1.0 means no zoom, 0.5 half size...
3118 * @ingroup Elm_Gesture_Layer
3121 _zoom_compute(Zoom_Type *st,
3126 double zoom_finger_factor)
3129 unsigned int tm_end = (st->zoom_mv.timestamp > st->zoom_mv1.timestamp) ?
3130 st->zoom_mv.timestamp : st->zoom_mv1.timestamp;
3132 Evas_Coord diam = _finger_gap_length_get(xx1, yy1, xx2, yy2,
3133 &st->info.x, &st->info.y);
3135 st->info.radius = diam / 2;
3139 st->zoom_base = diam;
3140 return st->info.zoom;
3143 if (st->zoom_distance_tolerance) /* zoom tolerance <> ZERO, means
3144 * zoom action NOT started yet */
3146 /* avoid jump with zoom value when break tolerance */
3147 if (diam < (st->zoom_base - st->zoom_distance_tolerance))
3149 st->zoom_base -= st->zoom_distance_tolerance;
3150 st->zoom_distance_tolerance = 0;
3153 /* avoid jump with zoom value when break tolerance */
3154 if (diam > (st->zoom_base + st->zoom_distance_tolerance))
3156 st->zoom_base += st->zoom_distance_tolerance;
3157 st->zoom_distance_tolerance = 0;
3163 /* We use factor only on the difference between gap-base */
3164 /* if gap=120, base=100, we get ((120-100)/100)=0.2*factor */
3165 rt = ((1.0) + ((((float)diam - (float)st->zoom_base) /
3166 (float)st->zoom_base) * zoom_finger_factor));
3168 /* Momentum: zoom per second: */
3169 st->info.momentum = _zoom_momentum_get(st, tm_end, rt);
3177 * This function handles zoom with mouse wheel.
3178 * thats a combination of wheel + CTRL key.
3179 * @param obj The gesture-layer object.
3180 * @param event_info Original input event pointer.
3181 * @param event_type Type of original input event.
3182 * @param g_type what Gesture we are testing.
3184 * @ingroup Elm_Gesture_Layer
3187 _zoom_with_wheel_test(Evas_Object *obj,
3189 Evas_Callback_Type event_type,
3190 Elm_Gesture_Type g_type)
3192 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
3194 if (!sd->gesture[g_type]) return;
3196 Gesture_Info *gesture_zoom = sd->gesture[g_type];
3197 Zoom_Type *st = gesture_zoom->data;
3198 Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
3199 if (!st) /* Allocated once on first time, used for zoom intermediate data */
3201 st = calloc(1, sizeof(Zoom_Type));
3202 gesture_zoom->data = st;
3203 _zoom_test_reset(gesture_zoom);
3208 case EVAS_CALLBACK_KEY_UP:
3210 Evas_Event_Key_Up *p = event_info;
3211 if ((!strcmp(p->key, "Control_L")) ||
3212 /* Test if we ended a zoom gesture when releasing CTRL */
3213 (!strcmp(p->key, "Control_R")))
3215 if ((st->zoom_wheel) &&
3216 ((gesture_zoom->state == ELM_GESTURE_STATE_START) ||
3217 /* User released CTRL after zooming */
3218 (gesture_zoom->state == ELM_GESTURE_STATE_MOVE)))
3220 st->info.momentum = _zoom_momentum_get
3221 (st, p->timestamp, st->info.zoom);
3223 ev_flag = _state_set
3224 (gesture_zoom, ELM_GESTURE_STATE_END, &st->info,
3226 _event_consume(sd, event_info, event_type, ev_flag);
3234 case EVAS_CALLBACK_MOUSE_WHEEL:
3237 Elm_Gesture_State s;
3238 if (!evas_key_modifier_is_set(
3239 ((Evas_Event_Mouse_Wheel *)event_info)->modifiers,
3240 "Control")) /* if using wheel witout CTRL after starting zoom */
3242 if ((st->zoom_wheel) &&
3243 ((gesture_zoom->state == ELM_GESTURE_STATE_START) ||
3244 (gesture_zoom->state == ELM_GESTURE_STATE_MOVE)))
3246 ev_flag = _state_set
3247 (gesture_zoom, ELM_GESTURE_STATE_END, &st->info,
3249 _event_consume(sd, event_info, event_type, ev_flag);
3254 return; /* Ignore mouse-wheel without control */
3257 /* Using mouse wheel with CTRL for zoom */
3258 /* (zoom_wheel == NULL) and (zoom_distance_tolerance == 0) we
3259 * continue a zoom gesture */
3260 if (st->zoom_wheel || (st->zoom_distance_tolerance == 0))
3263 s = ELM_GESTURE_STATE_MOVE;
3266 { /* On first wheel event, report START */
3267 Evas_Modifier_Mask mask = evas_key_modifier_mask_get(
3268 evas_object_evas_get(sd->target), "Control");
3270 s = ELM_GESTURE_STATE_START;
3271 if (!evas_object_key_grab
3272 (sd->target, "Control_L", mask, 0, EINA_FALSE))
3273 ERR("Failed to Grabbed CTRL_L");
3274 if (!evas_object_key_grab
3275 (sd->target, "Control_R", mask, 0, EINA_FALSE))
3276 ERR("Failed to Grabbed CTRL_R");
3279 st->zoom_distance_tolerance = 0; /* Cancel tolerance */
3280 st->zoom_wheel = (Evas_Event_Mouse_Wheel *)event_info;
3281 st->info.x = st->zoom_wheel->canvas.x;
3282 st->info.y = st->zoom_wheel->canvas.y;
3284 if (st->zoom_wheel->z < 0) /* zoom in */
3285 st->info.zoom += (sd->zoom_finger_factor * sd->zoom_wheel_factor);
3287 if (st->zoom_wheel->z > 0) /* zoom out */
3288 st->info.zoom -= (sd->zoom_finger_factor * sd->zoom_wheel_factor);
3290 if (st->info.zoom < 0.0)
3291 st->info.zoom = 0.0;
3293 st->info.momentum = _zoom_momentum_get
3294 (st, st->zoom_wheel->timestamp, st->info.zoom);
3296 ev_flag = _state_set(gesture_zoom, s, &st->info, force);
3297 _event_consume(sd, event_info, event_type, ev_flag);
3309 * This function is used to test zoom gesture.
3310 * user may combine zoom, rotation together.
3311 * so its possible that both will be detected from input.
3312 * (both are two-finger movement-oriented gestures)
3314 * @param obj The gesture-layer object.
3315 * @param event_info Pointer to recent input event.
3316 * @param event_type Recent input event type.
3317 * @param g_type what Gesture we are testing.
3319 * @ingroup Elm_Gesture_Layer
3322 _zoom_test(Evas_Object *obj,
3325 Evas_Callback_Type event_type,
3326 Elm_Gesture_Type g_type)
3328 /* Test for wheel zoom. */
3329 _zoom_with_wheel_test(obj, event_info, event_type, ELM_GESTURE_ZOOM);
3331 if (!_elm_config->glayer_zoom_finger_enable)
3336 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
3338 if (!sd->gesture[g_type]) return;
3340 Gesture_Info *gesture_zoom = sd->gesture[g_type];
3341 Zoom_Type *st = gesture_zoom->data;
3343 if (!st) /* Allocated once on first time, used for zoom data */
3345 st = calloc(1, sizeof(Zoom_Type));
3346 gesture_zoom->data = st;
3347 _zoom_test_reset(gesture_zoom);
3350 /* Start - new zoom testing, letting all fingers start */
3351 Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
3354 case EVAS_CALLBACK_MOUSE_MOVE:
3355 case EVAS_CALLBACK_MULTI_MOVE:
3356 /* if non-continues mode and gesture NOT started, ignore MOVE */
3357 if ((!sd->glayer_continues_enable) &&
3358 (!st->zoom_st.timestamp))
3361 case EVAS_CALLBACK_MOUSE_DOWN:
3362 case EVAS_CALLBACK_MULTI_DOWN:
3363 { /* Here we take care of zoom-start and zoom move */
3367 if (eina_list_count(sd->touched) > 2) /* Process zoom only
3371 ev_flag = _state_set
3372 (gesture_zoom, ELM_GESTURE_STATE_ABORT, &st->info,
3374 _event_consume(sd, event_info, event_type, ev_flag);
3379 if (!st->zoom_st.timestamp) /* Now scan touched-devices list
3380 * and find other finger */
3382 EINA_LIST_FOREACH(sd->touched, l, p)
3383 { /* Device of other finger <> pe device */
3384 if (p->device != pe->device)
3388 if (!p) /* Single finger on touch */
3391 /* Record down fingers */
3392 _event_consume(sd, event_info, event_type, ev_flag);
3393 memcpy(&st->zoom_st, pe, sizeof(Pointer_Event));
3394 memcpy(&st->zoom_st1, p, sizeof(Pointer_Event));
3396 /* Set mv field as well to be ready for MOVE events */
3397 memcpy(&st->zoom_mv, pe, sizeof(Pointer_Event));
3398 memcpy(&st->zoom_mv1, p, sizeof(Pointer_Event));
3400 /* Here we have zoom_st, zoom_st1 set, report START */
3401 /* Set zoom-base after BOTH down events recorded */
3402 /* Compute length of line between fingers zoom start */
3403 st->info.zoom = 1.0;
3404 st->zoom_base = _finger_gap_length_get
3405 (st->zoom_st1.x, st->zoom_st1.y, st->zoom_st.x, st->zoom_st.y,
3406 &st->info.x, &st->info.y);
3408 st->info.radius = st->zoom_base / 2;
3410 if ((gesture_zoom->state != ELM_GESTURE_STATE_START) &&
3411 /* zoom started with mouse-wheel, don't report twice */
3412 (gesture_zoom->state != ELM_GESTURE_STATE_MOVE))
3414 ev_flag = _state_set
3415 (gesture_zoom, ELM_GESTURE_STATE_START, &st->info,
3417 _event_consume(sd, event_info, event_type, ev_flag);
3420 return; /* Zoom started */
3421 } /* End of ZOOM_START handling */
3423 /* if we got here, we have (exacally) two fingers on surfce */
3424 /* we also after START, report MOVE */
3425 /* First detect which finger moved */
3426 if (pe->device == st->zoom_mv.device)
3427 memcpy(&st->zoom_mv, pe, sizeof(Pointer_Event));
3428 else if (pe->device == st->zoom_mv1.device)
3429 memcpy(&st->zoom_mv1, pe, sizeof(Pointer_Event));
3431 /* Compute change in zoom as fingers move */
3432 st->info.zoom = _zoom_compute(st,
3433 st->zoom_mv.x, st->zoom_mv.y,
3434 st->zoom_mv1.x, st->zoom_mv1.y,
3435 sd->zoom_finger_factor);
3437 if (!st->zoom_distance_tolerance) /* Zoom broke tolerance,
3440 double d = st->info.zoom - st->next_step;
3444 if (d >= sd->zoom_step) /* Report move in steps */
3446 st->next_step = st->info.zoom;
3448 ev_flag = _state_set(gesture_zoom,
3449 ELM_GESTURE_STATE_MOVE,
3450 &st->info, EINA_TRUE);
3451 _event_consume(sd, event_info, event_type, ev_flag);
3453 } /* End of ZOOM_MOVE handling */
3458 case EVAS_CALLBACK_MOUSE_UP:
3459 case EVAS_CALLBACK_MULTI_UP:
3460 /* Reset timestamp of finger-up.This is used later
3461 by _zoom_test_reset() to retain finger-down data */
3462 _event_consume(sd, event_info, event_type, ev_flag);
3463 if (((st->zoom_wheel) || (st->zoom_base)) &&
3464 (st->zoom_distance_tolerance == 0))
3466 ev_flag = _state_set(gesture_zoom, ELM_GESTURE_STATE_END,
3467 &st->info, EINA_FALSE);
3468 _event_consume(sd, event_info, event_type, ev_flag);
3473 /* if we got here not a ZOOM */
3474 /* Must be != undefined, if gesture started */
3475 if (gesture_zoom->state != ELM_GESTURE_STATE_UNDEFINED)
3477 ev_flag = _state_set
3478 (gesture_zoom, ELM_GESTURE_STATE_ABORT, &st->info,
3480 _event_consume(sd, event_info, event_type, ev_flag);
3483 _zoom_test_reset(gesture_zoom);
3493 _rotate_properties_get(Rotate_Type *st,
3500 /* FIXME: Fix momentum computation, it's wrong */
3501 double prev_angle = *angle;
3503 st->info.radius = _finger_gap_length_get(xx1, yy1, xx2, yy2,
3504 &st->info.x, &st->info.y) / 2;
3506 *angle = _angle_get(xx1, yy1, xx2, yy2);
3508 if (angle == &st->info.angle) /* Fingers are moving, compute momentum */
3510 unsigned int tm_start =
3511 (st->rotate_st.timestamp > st->rotate_st1.timestamp)
3512 ? st->rotate_st.timestamp : st->rotate_st1.timestamp;
3513 unsigned int tm_end =
3514 (st->rotate_mv.timestamp > st->rotate_mv1.timestamp)
3515 ? st->rotate_mv.timestamp : st->rotate_mv1.timestamp;
3517 unsigned int tm_total = tm_end - tm_start;
3518 if (tm_total) /* Momentum computed as:
3519 accumulated roation angle (deg) divided by time */
3522 if (((prev_angle < 90) && ((*angle) > 270)) ||
3523 /* We circle passing ZERO point */
3524 ((prev_angle > 270) && ((*angle) < 90)))
3526 prev_angle = (*angle);
3528 else m = prev_angle - (*angle);
3530 st->accum_momentum += m;
3532 if ((tm_end - st->prev_momentum_tm) < 100)
3533 st->prev_momentum += m;
3536 if (fabs(st->prev_momentum) < 0.002)
3537 st->accum_momentum = 0.0; /* reset momentum */
3539 st->prev_momentum = 0.0; /* Start again */
3542 st->prev_momentum_tm = tm_end;
3543 st->info.momentum = (st->accum_momentum * 1000) / tm_total;
3547 st->info.momentum = 0;
3553 * This function is used to test rotation gesture.
3554 * user may combine zoom, rotation together.
3555 * so its possible that both will be detected from input.
3556 * (both are two-finger movement-oriented gestures)
3558 * @param obj The gesture-layer object.
3559 * @param event_info Pointer to recent input event.
3560 * @param event_type Recent input event type.
3561 * @param g_type what Gesture we are testing.
3563 * @ingroup Elm_Gesture_Layer
3566 _rotate_test(Evas_Object *obj,
3569 Evas_Callback_Type event_type,
3570 Elm_Gesture_Type g_type)
3572 Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
3573 Gesture_Info *gesture;
3574 Rotate_Type *st = NULL;
3576 if (!_elm_config->glayer_rotate_finger_enable)
3582 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
3584 if (!sd->gesture[g_type]) return;
3586 gesture = sd->gesture[g_type];
3587 if (!gesture) return ;
3590 if (!st) /* Allocated once on first time */
3592 st = calloc(1, sizeof(Rotate_Type));
3594 _rotate_test_reset(gesture);
3599 case EVAS_CALLBACK_MOUSE_MOVE:
3600 case EVAS_CALLBACK_MULTI_MOVE:
3601 /* if non-continues mode and gesture NOT started, ignore MOVE */
3602 if ((!sd->glayer_continues_enable) &&
3603 (!st->rotate_st.timestamp))
3606 case EVAS_CALLBACK_MOUSE_DOWN:
3607 case EVAS_CALLBACK_MULTI_DOWN:
3608 { /* Here we take care of rotate-start and rotate move */
3612 if (eina_list_count(sd->touched) > 2) /* Process rotate only
3616 ev_flag = _state_set
3617 (gesture, ELM_GESTURE_STATE_ABORT, &st->info, EINA_FALSE);
3618 _event_consume(sd, event_info, event_type, ev_flag);
3623 if (!st->rotate_st.timestamp) /* Now scan touched-devices list
3624 * and find other finger */
3626 EINA_LIST_FOREACH(sd->touched, l, p)
3627 { /* Device of other finger <> pe device */
3628 if (p->device != pe->device)
3633 return; /* Single finger on touch */
3635 /* Record down fingers */
3636 _event_consume(sd, event_info, event_type, ev_flag);
3637 memcpy(&st->rotate_st, pe, sizeof(Pointer_Event));
3638 memcpy(&st->rotate_st1, p, sizeof(Pointer_Event));
3640 /* Set mv field as well to be ready for MOVE events */
3641 memcpy(&st->rotate_mv, pe, sizeof(Pointer_Event));
3642 memcpy(&st->rotate_mv1, p, sizeof(Pointer_Event));
3644 /* Here we have rotate_st, rotate_st1 set, report START */
3645 /* Set rotate-base after BOTH down events recorded */
3646 /* Compute length of line between fingers rotate start */
3647 _rotate_properties_get(st,
3648 st->rotate_st.x, st->rotate_st.y,
3649 st->rotate_st1.x, st->rotate_st1.y,
3650 &st->info.base_angle);
3652 ev_flag = _state_set(gesture, ELM_GESTURE_STATE_START,
3653 &st->info, EINA_FALSE);
3654 _event_consume(sd, event_info, event_type, ev_flag);
3656 return; /* Rotate started */
3657 } /* End of ROTATE_START handling */
3659 /* if we got here, we have (exacally) two fingers on surfce */
3660 /* we also after START, report MOVE */
3661 /* First detect which finger moved */
3662 if (pe->device == st->rotate_mv.device)
3663 memcpy(&st->rotate_mv, pe, sizeof(Pointer_Event));
3664 else if (pe->device == st->rotate_mv1.device)
3665 memcpy(&st->rotate_mv1, pe, sizeof(Pointer_Event));
3667 /* Compute change in rotate as fingers move */
3668 _rotate_properties_get(st,
3669 st->rotate_mv.x, st->rotate_mv.y,
3670 st->rotate_mv1.x, st->rotate_mv1.y,
3673 if (_on_rotation_broke_tolerance(st)) /* Rotation broke
3677 double d = st->info.angle - st->next_step;
3681 if (d >= sd->rotate_step) /* Report move in steps */
3683 st->next_step = st->info.angle;
3685 ev_flag = _state_set
3686 (gesture, ELM_GESTURE_STATE_MOVE, &st->info, EINA_TRUE);
3687 _event_consume(sd, event_info, event_type, ev_flag);
3689 } /* End of ROTATE_MOVE handling */
3694 case EVAS_CALLBACK_MOUSE_UP:
3695 case EVAS_CALLBACK_MULTI_UP:
3696 _event_consume(sd, event_info, event_type, ev_flag);
3697 /* Reset timestamp of finger-up.This is used later
3698 by rotate_test_reset() to retain finger-down data */
3699 if (st->rotate_angular_tolerance < 0)
3701 ev_flag = _state_set(gesture, ELM_GESTURE_STATE_END,
3702 &st->info, EINA_FALSE);
3703 _event_consume(sd, event_info, event_type, ev_flag);
3708 /* Must be != undefined, if gesture started */
3709 if (gesture->state != ELM_GESTURE_STATE_UNDEFINED)
3711 ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
3712 &st->info, EINA_FALSE);
3713 _event_consume(sd, event_info, event_type, ev_flag);
3716 _rotate_test_reset(gesture);
3725 _elm_gesture_layer_smart_disable(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
3727 Eina_Bool *ret = va_arg(*list, Eina_Bool *);
3728 if (elm_widget_disabled_get(obj))
3729 _callbacks_unregister(obj);
3731 _callbacks_register(obj);
3733 if (ret) *ret = EINA_TRUE;
3737 _elm_gesture_layer_smart_add(Eo *obj, void *_pd, va_list *list EINA_UNUSED)
3739 eo_do_super(obj, MY_CLASS, evas_obj_smart_add());
3741 elm_widget_sub_object_add(eo_parent_get(obj), obj);
3743 Elm_Gesture_Layer_Smart_Data *priv = _pd;
3745 priv->line_min_length =
3746 _elm_config->glayer_line_min_length * elm_config_finger_size_get();
3747 priv->zoom_distance_tolerance = _elm_config->glayer_zoom_distance_tolerance
3748 * elm_config_finger_size_get();
3749 priv->line_distance_tolerance = _elm_config->glayer_line_distance_tolerance
3750 * elm_config_finger_size_get();
3751 priv->zoom_finger_factor = _elm_config->glayer_zoom_finger_factor;
3752 /* mouse wheel zoom steps */
3753 priv->zoom_wheel_factor = _elm_config->glayer_zoom_wheel_factor;
3754 priv->rotate_angular_tolerance =
3755 _elm_config->glayer_rotate_angular_tolerance;
3756 priv->line_angular_tolerance = _elm_config->glayer_line_angular_tolerance;
3757 priv->flick_time_limit_ms = _elm_config->glayer_flick_time_limit_ms;
3758 priv->long_tap_start_timeout = _elm_config->glayer_long_tap_start_timeout;
3759 priv->repeat_events = EINA_TRUE;
3760 priv->glayer_continues_enable = _elm_config->glayer_continues_enable;
3762 /* FIXME: Hack to get around old configs - if too small, enlarge. */
3763 if (_elm_config->glayer_double_tap_timeout < 0.00001)
3764 _elm_config->glayer_double_tap_timeout = 0.25;
3765 priv->double_tap_timeout = _elm_config->glayer_double_tap_timeout;
3767 memset(priv->gesture, 0, sizeof(priv->gesture));
3770 static void _cbs_clean(Elm_Gesture_Layer_Smart_Data *sd, Elm_Gesture_Type idx, Elm_Gesture_State cb_type);
3773 _elm_gesture_layer_smart_del(Eo *obj, void *_pd, va_list *list EINA_UNUSED)
3775 Elm_Gesture_Layer_Smart_Data *sd = _pd;
3776 Pointer_Event *data;
3779 /* Clear all gestures intermediate data, stop any timers */
3781 /* FIXME: +1 because of the mistake in the enum. */
3782 Gesture_Info **gitr = sd->gesture + 1;
3783 Tests_Array_Funcs *fitr = _glayer_tests_array + 1;
3784 for (; fitr->reset; fitr++, gitr++)
3786 if (IS_TESTED_GESTURE(*gitr))
3791 /* First Free all gestures internal data structures */
3792 for (i = 0; i < ELM_GESTURE_LAST; i++)
3795 if (sd->gesture[i]->data)
3796 free(sd->gesture[i]->data);
3798 _cbs_clean(sd, i, ELM_GESTURE_STATE_START);
3799 _cbs_clean(sd, i, ELM_GESTURE_STATE_MOVE);
3800 _cbs_clean(sd, i, ELM_GESTURE_STATE_END);
3801 _cbs_clean(sd, i, ELM_GESTURE_STATE_ABORT);
3802 free(sd->gesture[i]);
3803 sd->gesture[i] = NULL; /* Referenced by _event_history_clear */
3805 if (sd->gest_taps_timeout) ecore_timer_del(sd->gest_taps_timeout);
3807 /* Then take care of clearing events */
3808 _event_history_clear(obj);
3809 sd->pending = eina_list_free(sd->pending);
3811 EINA_LIST_FREE(sd->touched, data)
3814 if (!elm_widget_disabled_get(obj))
3815 _callbacks_unregister(obj);
3818 eo_do_super(obj, MY_CLASS, evas_obj_smart_del());
3822 elm_gesture_layer_add(Evas_Object *parent)
3824 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
3825 Evas_Object *obj = eo_add(MY_CLASS, parent);
3831 _constructor(Eo *obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
3833 eo_do_super(obj, MY_CLASS, eo_constructor());
3834 eo_do(obj, evas_obj_type_set(MY_CLASS_NAME));
3838 elm_gesture_layer_hold_events_get(const Evas_Object *obj)
3840 ELM_GESTURE_LAYER_CHECK(obj) EINA_FALSE;
3841 Eina_Bool ret = EINA_FALSE;
3842 eo_do((Eo *) obj, elm_obj_gesture_layer_hold_events_get(&ret));
3847 _hold_events_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
3849 Eina_Bool *ret = va_arg(*list, Eina_Bool *);
3850 Elm_Gesture_Layer_Smart_Data *sd = _pd;
3851 *ret = !sd->repeat_events;
3855 elm_gesture_layer_hold_events_set(Evas_Object *obj,
3856 Eina_Bool hold_events)
3858 ELM_GESTURE_LAYER_CHECK(obj);
3859 eo_do(obj, elm_obj_gesture_layer_hold_events_set(hold_events));
3863 _hold_events_set(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
3865 Eina_Bool hold_events = va_arg(*list, int);
3866 Elm_Gesture_Layer_Smart_Data *sd = _pd;
3868 sd->repeat_events = !(!!hold_events);
3872 elm_gesture_layer_zoom_step_get(const Evas_Object *obj)
3874 ELM_GESTURE_LAYER_CHECK(obj) 0;
3876 eo_do((Eo *) obj, elm_obj_gesture_layer_zoom_step_get(&ret));
3881 _zoom_step_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
3883 double *ret = va_arg(*list, double *);
3884 Elm_Gesture_Layer_Smart_Data *sd = _pd;
3885 *ret = sd->zoom_step;
3889 elm_gesture_layer_zoom_step_set(Evas_Object *obj,
3892 ELM_GESTURE_LAYER_CHECK(obj);
3893 eo_do(obj, elm_obj_gesture_layer_zoom_step_set(step));
3897 _zoom_step_set(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
3899 double step = va_arg(*list, double);
3900 Elm_Gesture_Layer_Smart_Data *sd = _pd;
3902 if (step < 0) return;
3904 sd->zoom_step = step;
3908 elm_gesture_layer_rotate_step_get(const Evas_Object *obj)
3910 ELM_GESTURE_LAYER_CHECK(obj) 0;
3912 eo_do((Eo *) obj, elm_obj_gesture_layer_rotate_step_get(&ret));
3917 _rotate_step_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
3919 double *ret = va_arg(*list, double *);
3920 Elm_Gesture_Layer_Smart_Data *sd = _pd;
3921 *ret = sd->rotate_step;
3925 elm_gesture_layer_rotate_step_set(Evas_Object *obj,
3928 ELM_GESTURE_LAYER_CHECK(obj);
3929 eo_do(obj, elm_obj_gesture_layer_rotate_step_set(step));
3933 _rotate_step_set(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
3935 double step = va_arg(*list, double);
3936 Elm_Gesture_Layer_Smart_Data *sd = _pd;
3938 if (step < 0) return;
3940 sd->rotate_step = step;
3944 elm_gesture_layer_attach(Evas_Object *obj,
3945 Evas_Object *target)
3947 ELM_GESTURE_LAYER_CHECK(obj) EINA_FALSE;
3948 Eina_Bool ret = EINA_FALSE;
3949 eo_do(obj, elm_obj_gesture_layer_attach(target, &ret));
3954 _attach(Eo *obj, void *_pd, va_list *list)
3956 Evas_Object *target = va_arg(*list, Evas_Object *);
3957 Eina_Bool *ret = va_arg(*list, Eina_Bool *);
3958 Elm_Gesture_Layer_Smart_Data *sd = _pd;
3959 if (ret) *ret = EINA_FALSE;
3961 if (!target) return;
3963 /* if was attached before, unregister callbacks first */
3965 _callbacks_unregister(obj);
3967 sd->target = target;
3969 _callbacks_register(obj);
3970 if (ret) *ret = EINA_TRUE;
3974 _cbs_clean(Elm_Gesture_Layer_Smart_Data *sd,
3975 Elm_Gesture_Type idx,
3976 Elm_Gesture_State cb_type)
3978 if (!sd->gesture[idx]) return;
3981 EINA_INLIST_FREE(sd->gesture[idx]->cbs[cb_type], cb_info)
3983 sd->gesture[idx]->cbs[cb_type] = eina_inlist_remove(
3984 sd->gesture[idx]->cbs[cb_type], EINA_INLIST_GET(cb_info));
3987 SET_TEST_BIT(sd->gesture[idx]);
3991 elm_gesture_layer_cb_set(Evas_Object *obj,
3992 Elm_Gesture_Type idx,
3993 Elm_Gesture_State cb_type,
3994 Elm_Gesture_Event_Cb cb,
3997 ELM_GESTURE_LAYER_CHECK(obj);
3998 eo_do(obj, elm_obj_gesture_layer_cb_set(idx, cb_type, cb, data));
4002 _cb_set(Eo *obj, void *_pd, va_list *list)
4004 Elm_Gesture_Type idx = va_arg(*list, Elm_Gesture_Type);
4005 Elm_Gesture_State cb_type = va_arg(*list, Elm_Gesture_State);
4006 Elm_Gesture_Event_Cb cb = va_arg(*list, Elm_Gesture_Event_Cb);
4007 void *data = va_arg(*list, void *);
4009 Elm_Gesture_Layer_Smart_Data *sd = _pd;
4011 /* Clear gesture intermediate data, stop any timers */
4012 if (IS_TESTED_GESTURE(sd->gesture[idx]))
4013 _glayer_tests_array[idx].reset(sd->gesture[idx]);
4015 _cbs_clean(sd, idx, cb_type); // for ABI compat.
4016 eo_do(obj, elm_obj_gesture_layer_cb_add(idx, cb_type, cb, data));
4020 elm_gesture_layer_cb_add(Evas_Object *obj,
4021 Elm_Gesture_Type idx,
4022 Elm_Gesture_State cb_type,
4023 Elm_Gesture_Event_Cb cb,
4026 ELM_GESTURE_LAYER_CHECK(obj);
4027 eo_do(obj, elm_obj_gesture_layer_cb_add(idx, cb_type, cb, data));
4031 _cb_add(Eo *obj, void *_pd, va_list *list)
4033 Elm_Gesture_Type idx = va_arg(*list, Elm_Gesture_Type);
4034 Elm_Gesture_State cb_type = va_arg(*list, Elm_Gesture_State);
4035 Elm_Gesture_Event_Cb cb = va_arg(*list, Elm_Gesture_Event_Cb);
4036 void *data = va_arg(*list, void *);
4041 Elm_Gesture_Layer_Smart_Data *sd = _pd;
4043 if (!sd->gesture[idx])
4044 sd->gesture[idx] = calloc(1, sizeof(Gesture_Info));
4045 if (!sd->gesture[idx]) return;
4047 Func_Data *cb_info = calloc(1, sizeof(*cb_info));
4048 if (!cb_info) return;
4050 cb_info->user_data = data;
4052 p = sd->gesture[idx];
4055 p->cbs[cb_type] = eina_inlist_append(p->cbs[cb_type],
4056 EINA_INLIST_GET(cb_info));
4057 p->state = ELM_GESTURE_STATE_UNDEFINED;
4062 elm_gesture_layer_cb_del(Evas_Object *obj,
4063 Elm_Gesture_Type idx,
4064 Elm_Gesture_State cb_type,
4065 Elm_Gesture_Event_Cb cb,
4068 ELM_GESTURE_LAYER_CHECK(obj);
4069 eo_do(obj, elm_obj_gesture_layer_cb_del(idx, cb_type, cb, data));
4073 _cb_del(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
4075 Elm_Gesture_Type idx = va_arg(*list, Elm_Gesture_Type);
4076 Elm_Gesture_State cb_type = va_arg(*list, Elm_Gesture_State);
4077 Elm_Gesture_Event_Cb cb = va_arg(*list, Elm_Gesture_Event_Cb);
4078 void *data = va_arg(*list, void *);
4080 Elm_Gesture_Layer_Smart_Data *sd = _pd;
4082 if (!sd->gesture[idx]) return;
4086 EINA_INLIST_FOREACH_SAFE(sd->gesture[idx]->cbs[cb_type], itr, cb_info)
4088 if (cb_info->cb == cb && cb_info->user_data == data)
4090 /* Clear gesture intermediate data, stop any timers */
4091 if (IS_TESTED_GESTURE(sd->gesture[idx]))
4092 _glayer_tests_array[idx].reset(sd->gesture[idx]);
4094 sd->gesture[idx]->cbs[cb_type] = eina_inlist_remove(
4095 sd->gesture[idx]->cbs[cb_type], EINA_INLIST_GET(cb_info));
4097 SET_TEST_BIT(sd->gesture[idx]);
4104 elm_gesture_layer_line_min_length_set(Evas_Object *obj, int line_min_length)
4106 ELM_GESTURE_LAYER_CHECK(obj);
4107 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
4108 sd->line_min_length = line_min_length;
4113 elm_gesture_layer_line_min_length_get(const Evas_Object *obj)
4115 ELM_GESTURE_LAYER_CHECK(obj) 0;
4116 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
4117 return sd->line_min_length;
4121 elm_gesture_layer_zoom_distance_tolerance_set(Evas_Object *obj, Evas_Coord zoom_distance_tolerance)
4123 ELM_GESTURE_LAYER_CHECK(obj);
4124 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
4125 sd->zoom_distance_tolerance = zoom_distance_tolerance;
4129 elm_gesture_layer_zoom_distance_tolerance_get(const Evas_Object *obj)
4131 ELM_GESTURE_LAYER_CHECK(obj) 0;
4132 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
4133 return sd->zoom_distance_tolerance;
4137 elm_gesture_layer_line_distance_tolerance_set(Evas_Object *obj, Evas_Coord line_distance_tolerance)
4139 ELM_GESTURE_LAYER_CHECK(obj);
4140 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
4141 sd->line_distance_tolerance = line_distance_tolerance;
4145 elm_gesture_layer_line_distance_tolerance_get(const Evas_Object *obj)
4147 ELM_GESTURE_LAYER_CHECK(obj) 0;
4148 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
4149 return sd->line_distance_tolerance;
4153 elm_gesture_layer_line_angular_tolerance_set(Evas_Object *obj, double line_angular_tolerance)
4155 ELM_GESTURE_LAYER_CHECK(obj);
4156 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
4157 sd->line_angular_tolerance = line_angular_tolerance;
4161 elm_gesture_layer_line_angular_tolerance_get(const Evas_Object *obj)
4163 ELM_GESTURE_LAYER_CHECK(obj) 0.0;
4164 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
4165 return sd->line_angular_tolerance;
4169 elm_gesture_layer_zoom_wheel_factor_set(Evas_Object *obj, double zoom_wheel_factor)
4171 ELM_GESTURE_LAYER_CHECK(obj);
4172 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
4173 sd->zoom_wheel_factor = zoom_wheel_factor;
4177 elm_gesture_layer_zoom_wheel_factor_get(const Evas_Object *obj)
4179 ELM_GESTURE_LAYER_CHECK(obj) 0.0;
4180 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
4181 return sd->zoom_wheel_factor;
4185 elm_gesture_layer_zoom_finger_factor_set(Evas_Object *obj, double zoom_finger_factor)
4187 ELM_GESTURE_LAYER_CHECK(obj);
4188 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
4189 sd->zoom_finger_factor = zoom_finger_factor;
4193 elm_gesture_layer_zoom_finger_factor_get(const Evas_Object *obj)
4195 ELM_GESTURE_LAYER_CHECK(obj) 0.0;
4196 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
4197 return sd->zoom_finger_factor;
4201 elm_gesture_layer_rotate_angular_tolerance_set(Evas_Object *obj, double rotate_angular_tolerance)
4203 ELM_GESTURE_LAYER_CHECK(obj);
4204 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
4205 sd->rotate_angular_tolerance = rotate_angular_tolerance;
4209 elm_gesture_layer_rotate_angular_tolerance_get(const Evas_Object *obj)
4211 ELM_GESTURE_LAYER_CHECK(obj) 0.0;
4212 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
4213 return sd->rotate_angular_tolerance;
4217 elm_gesture_layer_flick_time_limit_ms_set(Evas_Object *obj, unsigned int flick_time_limit_ms)
4219 ELM_GESTURE_LAYER_CHECK(obj);
4220 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
4221 sd->flick_time_limit_ms = flick_time_limit_ms;
4225 elm_gesture_layer_flick_time_limit_ms_get(const Evas_Object *obj)
4227 ELM_GESTURE_LAYER_CHECK(obj) 0;
4228 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
4229 return sd->flick_time_limit_ms;
4233 elm_gesture_layer_long_tap_start_timeout_set(Evas_Object *obj, double long_tap_start_timeout)
4235 ELM_GESTURE_LAYER_CHECK(obj);
4236 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
4237 sd->long_tap_start_timeout = long_tap_start_timeout;
4241 elm_gesture_layer_long_tap_start_timeout_get(const Evas_Object *obj)
4243 ELM_GESTURE_LAYER_CHECK(obj) 0.0;
4244 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
4245 return sd->long_tap_start_timeout;
4249 elm_gesture_layer_continues_enable_set(Evas_Object *obj, Eina_Bool continues_enable)
4251 ELM_GESTURE_LAYER_CHECK(obj);
4252 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
4253 sd->glayer_continues_enable = continues_enable;
4257 elm_gesture_layer_continues_enable_get(const Evas_Object *obj)
4259 ELM_GESTURE_LAYER_CHECK(obj) 0.0;
4260 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
4261 return sd->glayer_continues_enable;
4265 elm_gesture_layer_double_tap_timeout_set(Evas_Object *obj, double double_tap_timeout)
4267 ELM_GESTURE_LAYER_CHECK(obj);
4268 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
4269 sd->double_tap_timeout = double_tap_timeout;
4273 elm_gesture_layer_double_tap_timeout_get(const Evas_Object *obj)
4275 ELM_GESTURE_LAYER_CHECK(obj) 0.0;
4276 ELM_GESTURE_LAYER_DATA_GET(obj, sd);
4277 return sd->double_tap_timeout;
4281 elm_gesture_layer_tap_finger_size_set(Evas_Object *obj,
4284 ELM_GESTURE_LAYER_CHECK(obj);
4285 eo_do(obj, elm_obj_gesture_layer_tap_finger_size_set(sz));
4289 _tap_finger_size_set(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
4291 Evas_Coord sz = va_arg(*list, Evas_Coord);
4292 Elm_Gesture_Layer_Smart_Data *sd = _pd;
4295 sz = 0; /* Should not be negative, will reset to system value */
4297 sd->tap_finger_size = sz;
4301 elm_gesture_layer_tap_finger_size_get(const Evas_Object *obj)
4303 ELM_GESTURE_LAYER_CHECK(obj) elm_config_finger_size_get();
4305 eo_do((Eo *) obj, elm_obj_gesture_layer_tap_finger_size_get(&ret));
4310 _tap_finger_size_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
4312 Evas_Coord *ret = va_arg(*list, Evas_Coord *);
4313 Elm_Gesture_Layer_Smart_Data *sd = _pd;
4314 *ret = sd->tap_finger_size;
4318 _class_constructor(Eo_Class *klass)
4320 const Eo_Op_Func_Description func_desc[] = {
4321 EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_CONSTRUCTOR), _constructor),
4323 EO_OP_FUNC(EVAS_OBJ_SMART_ID(EVAS_OBJ_SMART_SUB_ID_ADD), _elm_gesture_layer_smart_add),
4324 EO_OP_FUNC(EVAS_OBJ_SMART_ID(EVAS_OBJ_SMART_SUB_ID_DEL), _elm_gesture_layer_smart_del),
4326 EO_OP_FUNC(ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_DISABLE), _elm_gesture_layer_smart_disable),
4328 EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_HOLD_EVENTS_GET), _hold_events_get),
4329 EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_HOLD_EVENTS_SET), _hold_events_set),
4330 EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_ZOOM_STEP_GET), _zoom_step_get),
4331 EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_ZOOM_STEP_SET), _zoom_step_set),
4332 EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_ROTATE_STEP_GET), _rotate_step_get),
4333 EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_ROTATE_STEP_SET), _rotate_step_set),
4334 EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_ATTACH), _attach),
4335 EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_CB_SET), _cb_set),
4336 EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_TAP_FINGER_SIZE_SET), _tap_finger_size_set),
4337 EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_TAP_FINGER_SIZE_GET), _tap_finger_size_get),
4338 EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_CB_ADD), _cb_add),
4339 EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_CB_DEL), _cb_del),
4342 eo_class_funcs_set(klass, func_desc);
4344 evas_smart_legacy_type_register(MY_CLASS_NAME, klass);
4347 static const Eo_Op_Description op_desc[] = {
4348 EO_OP_DESCRIPTION(ELM_OBJ_GESTURE_LAYER_SUB_ID_HOLD_EVENTS_GET, "Call this function to get repeat-events settings."),
4349 EO_OP_DESCRIPTION(ELM_OBJ_GESTURE_LAYER_SUB_ID_HOLD_EVENTS_SET, "This function is to make gesture-layer repeat events."),
4350 EO_OP_DESCRIPTION(ELM_OBJ_GESTURE_LAYER_SUB_ID_ZOOM_STEP_GET, "This function returns step-value for zoom action."),
4351 EO_OP_DESCRIPTION(ELM_OBJ_GESTURE_LAYER_SUB_ID_ZOOM_STEP_SET, "This function sets step-value for zoom action."),
4352 EO_OP_DESCRIPTION(ELM_OBJ_GESTURE_LAYER_SUB_ID_ROTATE_STEP_GET, "This function returns step-value for rotate action."),
4353 EO_OP_DESCRIPTION(ELM_OBJ_GESTURE_LAYER_SUB_ID_ROTATE_STEP_SET, "This function sets step-value for rotate action."),
4354 EO_OP_DESCRIPTION(ELM_OBJ_GESTURE_LAYER_SUB_ID_ATTACH, "Attach a given gesture layer widget to an Evas object, thus setting the widget's target."),
4355 EO_OP_DESCRIPTION(ELM_OBJ_GESTURE_LAYER_SUB_ID_CB_SET, "Use function to set callbacks to be notified about change of state of gesture."),
4356 EO_OP_DESCRIPTION(ELM_OBJ_GESTURE_LAYER_SUB_ID_TAP_FINGER_SIZE_SET, "Use function to set valid touch-area size for finger."),
4357 EO_OP_DESCRIPTION(ELM_OBJ_GESTURE_LAYER_SUB_ID_TAP_FINGER_SIZE_GET, "This function returns the valid touch-area size for finger."),
4358 EO_OP_DESCRIPTION(ELM_OBJ_GESTURE_LAYER_SUB_ID_CB_ADD, "Use function to add callbacks to be notified about change of state of gesture."),
4359 EO_OP_DESCRIPTION(ELM_OBJ_GESTURE_LAYER_SUB_ID_CB_DEL, "Use function to remove added callbacks."),
4360 EO_OP_DESCRIPTION_SENTINEL
4363 static const Eo_Class_Description class_desc = {
4366 EO_CLASS_TYPE_REGULAR,
4367 EO_CLASS_DESCRIPTION_OPS(&ELM_OBJ_GESTURE_LAYER_BASE_ID, op_desc, ELM_OBJ_GESTURE_LAYER_SUB_ID_LAST),
4369 sizeof(Elm_Gesture_Layer_Smart_Data),
4374 EO_DEFINE_CLASS(elm_obj_gesture_layer_class_get, &class_desc, ELM_OBJ_WIDGET_CLASS, NULL);