3 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
5 #include <Elementary.h>
9 #define SMART_NAME "elm_touch"
10 #define API_ENTRY Smart_Data *sd; sd = evas_object_smart_data_get(obj); if ((!obj) || (!sd) || (evas_object_type_get(obj) && strcmp(evas_object_type_get(obj), SMART_NAME)))
11 #define INTERNAL_ENTRY Smart_Data *sd; sd = evas_object_smart_data_get(obj); if (!sd) return;
13 #define PRESS_TIME 250 // ms
14 #define RELEASE_TIME 50 // ms
15 #define LONG_HOLD_TIME 500 // ms
18 #define DEFAULT_FRAMERATE 60
19 #define DOUBLE_ERROR 0.00001
22 #define DBL_TAP_DISTANCE 30 // pixel
23 #define DRAG_THRESHOLD 3 // pixel
24 #define INIT_DRAG_THRESHOLD 15 // pixel
25 #define MOVE_HISTORY_SIZE 5
26 #define MAX_MOVE_DISTANCE 15
27 #define FLICK_THRESHOLD 5
30 #define MOVE_THRESHOLD 15
31 #define FINGER_DISTANCE 10
33 typedef struct _Mouse_Data Mouse_Data;
43 typedef enum _Two_Drag_Mode
51 typedef struct _Two_Mouse_Data Two_Mouse_Data;
53 struct _Two_Mouse_Data
60 typedef struct _Three_Mouse_Data Three_Mouse_Data;
62 struct _Three_Mouse_Data
69 typedef enum _Touch_State
74 TOUCH_STATE_DOWN_UP_DOWN,
79 TOUCH_STATE_THREE_DOWN
82 typedef enum _One_Drag_Mode
89 typedef struct _Flick_Data Flick_Data;
94 Evas_Coord_Point last;
95 Evas_Coord_Point avg_distance;
98 typedef struct _Mouse_Diff_Data Mouse_Diff_Data;
100 struct _Mouse_Diff_Data
106 typedef struct _Smart_Data Smart_Data;
110 Evas_Object *smart_obj;
111 Evas_Object *child_obj;
117 One_Drag_Mode one_drag_mode;
118 Eina_Bool is_one_drag_mode;
119 Two_Drag_Mode two_drag_mode;
123 int last_move_history_index;
124 int move_history_count;
125 Flick_Data flick_data;
126 Mouse_Diff_Data move_history[MOVE_HISTORY_SIZE];
128 Mouse_Data first_down[N_FINGER];
129 Mouse_Data last_down[N_FINGER];
130 Mouse_Data last_drag[N_FINGER];
132 Ecore_Animator *animator_move;
133 Ecore_Animator *animator_flick;
134 Ecore_Animator *animator_two_move;
137 Ecore_Timer *press_timer;
138 Ecore_Timer *long_press_timer;
139 Ecore_Timer *release_timer;
140 Ecore_Timer *press_release_timer;
143 /* local subsystem functions */
145 static float _smart_velocity_easeinoutcubic(int index);
146 static void _smart_mouse_down(void *data, Evas *e, Evas_Object *obj, void *ev);
147 static void _smart_mouse_up(void *data, Evas *e, Evas_Object *obj, void *ev);
148 static void _smart_mouse_move(void *data, Evas *e, Evas_Object *obj, void *ev);
149 static void _smart_multi_down(void *data, Evas *e, Evas_Object *obj, void *ev);
150 static void _smart_multi_up(void *data, Evas *e, Evas_Object *obj, void *ev);
151 static void _smart_multi_move(void *data, Evas *e, Evas_Object *obj, void *ev);
152 // animator callbacks
153 static int _smart_animation_move(void *data);
154 static int _smart_animation_flick(void *data);
155 static int _smart_animation_two_move(void *data);
156 // enter mode functions
157 static void _smart_enter_none(Smart_Data *sd);
158 static void _smart_enter_down(Smart_Data *sd);
159 static void _smart_enter_down_up(Smart_Data *sd, int downTime, int time);
160 static void _smart_enter_down_up_down(Smart_Data *sd);
161 static void _smart_enter_hold(Smart_Data *sd);
162 static void _smart_enter_drag(Smart_Data *sd);
163 static void _smart_enter_two_down(Smart_Data *sd);
164 static void _smart_enter_two_drag(Smart_Data *sd);
165 static void _smart_enter_three_down(Smart_Data *sd);
167 static void _smart_emit_press(Smart_Data *sd);
168 static void _smart_emit_tap(Smart_Data *sd);
169 static void _smart_emit_double_tap(Smart_Data *sd);
170 static void _smart_emit_long_hold(Smart_Data *sd);
171 static void _smart_emit_release(Smart_Data *sd);
172 static void _smart_emit_two_press(Smart_Data *sd);
173 static void _smart_emit_two_tap(Smart_Data *sd);
174 static void _smart_emit_two_move_start(Smart_Data *sd);
175 static void _smart_emit_two_move(Smart_Data *sd);
176 static void _smart_emit_two_move_end(Smart_Data *sd);
177 static void _smart_emit_three_press(Smart_Data *sd);
178 static void _smart_emit_three_tap(Smart_Data *sd);
180 static int _smart_press_timer_handler(void *data);
181 static int _smart_long_press_timer_handler(void *data);
182 static int _smart_release_timer_handler(void *data);
183 static int _smart_press_release_timer_handler(void *data);
185 static void _smart_save_move_history(Smart_Data *sd, int x, int y, int dx, int dy);
186 static void _smart_start_flick(Smart_Data *sd);
187 static void _smart_stop_animator_move(Smart_Data *sd);
188 static void _smart_stop_animator_flick(Smart_Data *sd);
189 static void _smart_stop_animator_two_move(Smart_Data *sd);
190 static Two_Drag_Mode _smart_check_two_drag_mode(Smart_Data *sd);
191 static void _smart_set_first_down(Smart_Data *sd, int index, Mouse_Data *data);
192 static void _smart_set_last_down(Smart_Data *sd, int index, Mouse_Data *data);
193 static void _smart_set_last_drag(Smart_Data *sd, int index, Mouse_Data *data);
194 static void _smart_stop_all_timers(Smart_Data *sd);
195 static void _smart_init(void);
196 static void _smart_del(Evas_Object *obj);
197 static void _smart_add(Evas_Object *obj);
199 /* local subsystem globals */
200 static Evas_Smart *_smart = NULL;
202 /* externally accessible functions */
204 _elm_smart_touch_add(Evas *evas)
207 return evas_object_smart_add(evas, _smart);
211 _elm_smart_touch_child_set(Evas_Object *obj, Evas_Object *child)
214 if (child == sd->child_obj) return;
216 if (sd->child_obj) // delete callbacks of old object
218 evas_object_event_callback_del(sd->child_obj, EVAS_CALLBACK_MOUSE_DOWN, _smart_mouse_down);
219 evas_object_event_callback_del(sd->child_obj, EVAS_CALLBACK_MOUSE_UP, _smart_mouse_up);
220 evas_object_event_callback_del(sd->child_obj, EVAS_CALLBACK_MOUSE_MOVE, _smart_mouse_move);
221 evas_object_event_callback_del(sd->child_obj, EVAS_CALLBACK_MULTI_DOWN, _smart_multi_down);
222 evas_object_event_callback_del(sd->child_obj, EVAS_CALLBACK_MULTI_UP, _smart_multi_up);
223 evas_object_event_callback_del(sd->child_obj, EVAS_CALLBACK_MULTI_MOVE, _smart_multi_move);
224 _smart_stop_all_timers(sd);
225 _smart_stop_animator_move(sd);
226 _smart_stop_animator_flick(sd);
227 _smart_stop_animator_two_move(sd);
229 sd->child_obj = NULL;
234 sd->child_obj = child;
237 evas_object_event_callback_add(child, EVAS_CALLBACK_MOUSE_DOWN, _smart_mouse_down, sd);
238 evas_object_event_callback_add(child, EVAS_CALLBACK_MOUSE_UP, _smart_mouse_up, sd);
239 evas_object_event_callback_add(child, EVAS_CALLBACK_MOUSE_MOVE, _smart_mouse_move, sd);
240 evas_object_event_callback_add(child, EVAS_CALLBACK_MULTI_DOWN, _smart_multi_down, sd);
241 evas_object_event_callback_add(child, EVAS_CALLBACK_MULTI_UP, _smart_multi_up, sd);
242 evas_object_event_callback_add(child, EVAS_CALLBACK_MULTI_MOVE, _smart_multi_move, sd);
244 _smart_enter_none(sd);
246 sd->is_one_drag_mode = EINA_TRUE;
249 evas_object_smart_callback_call(sd->smart_obj, "changed", NULL);
253 _elm_smart_touch_start(Evas_Object *obj)
256 if (sd->running) return;
258 sd->running = EINA_TRUE;
259 _smart_enter_none(sd);
263 _elm_smart_touch_stop(Evas_Object *obj)
266 sd->running = EINA_FALSE;
267 _smart_stop_all_timers(sd);
268 _smart_stop_animator_move(sd);
269 _smart_stop_animator_flick(sd);
270 _smart_stop_animator_two_move(sd);
271 _smart_enter_none(sd);
275 _elm_smart_touch_reset(Evas_Object *obj)
278 _smart_stop_all_timers(sd);
279 _smart_stop_animator_move(sd);
280 _smart_stop_animator_flick(sd);
281 _smart_stop_animator_two_move(sd);
282 _smart_enter_none(sd);
286 _elm_smart_touch_screen_angle_update(Evas_Object *obj, int screen_angle)
289 sd->screen_angle = screen_angle;
293 _elm_smart_touch_is_one_drag_mode_enable(Evas_Object *obj, Eina_Bool is_one_drag_mode)
296 sd->is_one_drag_mode = is_one_drag_mode;
299 /* local subsystem functions */
300 /** reference from htsd://hosted.zeh.com.br/tweener/docs/en-us/misc/transitions.html
301 * Easing equation function for a cubic (t^3) easing in/out: acceleration until halfway, then deceleration
302 * @param t Number Current time (in frames or seconds)
303 * @param b Number Starting value
304 * @param c Number Change needed in value
305 * @param d Number Expected easing duration (in frames or seconds)
306 * @return Number The correct value
307 public static function easeInOutCubic (t:Number, b:Number, c:Number, d:Number, p_params:Object):Number {
308 if ((t/=d/2) < 1) return c/2*t*t*t + b;
309 return c/2*((t-=2)*t*t + 2) + b;
313 _smart_velocity_easeinoutcubic(int index)
316 float t = d - index; // we want to get reversed value
318 if ((t /= (d / 2)) < 1)
320 return (c / 2) * t * t * t;
323 return (c / 2) * (t * t * t + 2);
327 /* mouse callbacks */
329 _smart_mouse_down(void *data, Evas *e, Evas_Object *obj, void *ev)
332 Evas_Event_Mouse_Down *event;
333 Mouse_Data mouse_data;
336 if (!sd || sd->running == EINA_FALSE) return;
338 event = (Evas_Event_Mouse_Down*)ev;
342 case TOUCH_STATE_NONE:
343 case TOUCH_STATE_DRAG:
344 mouse_data.x = event->canvas.x;
345 mouse_data.y = event->canvas.y;
346 mouse_data.time = event->timestamp;
347 mouse_data.device = -1;
348 _smart_set_first_down(sd, 0, &mouse_data);
349 _smart_set_last_down(sd, 0, &mouse_data);
350 _smart_set_last_drag(sd, 0, &mouse_data);
351 _smart_enter_down(sd);
354 case TOUCH_STATE_DOWN_UP:
355 if (event->flags == EVAS_BUTTON_DOUBLE_CLICK) {
356 mouse_data.x = event->canvas.x;
357 mouse_data.y = event->canvas.y;
358 mouse_data.time = event->timestamp;
359 mouse_data.device = -1;
360 _smart_set_last_down(sd, 0, &mouse_data);
361 _smart_set_last_drag(sd, 0, &mouse_data);
362 _smart_enter_down_up_down(sd);
372 _smart_mouse_up(void *data, Evas *e, Evas_Object *obj, void *ev)
376 Evas_Event_Mouse_Up *event;
378 if (!sd || sd->running == EINA_FALSE) return;
380 event = (Evas_Event_Mouse_Up*)ev;
384 case TOUCH_STATE_DOWN:
385 _smart_stop_animator_move(sd);
386 _smart_stop_animator_flick(sd);
387 _smart_enter_down_up(sd, (event->timestamp - sd->last_down[0].time), event->timestamp);
390 case TOUCH_STATE_DOWN_UP_DOWN:
392 int dx = sd->last_down[0].x - sd->first_down[0].x;
393 int dy = sd->last_down[0].y - sd->first_down[0].y;
394 if ((dx * dx + dy * dy) <= (DBL_TAP_DISTANCE * DBL_TAP_DISTANCE))
395 _smart_emit_double_tap(sd);
396 _smart_stop_all_timers(sd);
397 _smart_enter_none(sd);
400 case TOUCH_STATE_HOLD:
401 _smart_emit_release(sd);
402 _smart_stop_all_timers(sd);
403 _smart_enter_none(sd);
406 case TOUCH_STATE_DRAG:
407 _smart_emit_release(sd);
408 _smart_start_flick(sd);
411 case TOUCH_STATE_TWO_DOWN:
412 _smart_emit_two_tap(sd);
413 _smart_stop_all_timers(sd);
414 _smart_enter_none(sd);
417 case TOUCH_STATE_TWO_DRAG:
418 _smart_stop_animator_two_move(sd);
419 _smart_stop_all_timers(sd);
420 _smart_enter_none(sd);
423 case TOUCH_STATE_THREE_DOWN:
424 _smart_emit_three_tap(sd);
425 _smart_stop_all_timers(sd);
426 _smart_enter_none(sd);
430 _smart_emit_release(sd);
431 _smart_stop_all_timers(sd);
432 _smart_enter_none(sd);
433 DBG("\nERROR: wrong state in mouse_up\n\n");
440 _smart_mouse_move(void *data, Evas *e, Evas_Object *obj, void *ev)
444 if (!sd || sd->running == EINA_FALSE) return;
446 Evas_Event_Mouse_Move *event = (Evas_Event_Mouse_Move*)ev;
450 Mouse_Data mouse_data;
451 mouse_data.x = event->cur.canvas.x;
452 mouse_data.y = event->cur.canvas.y;
453 mouse_data.time = event->timestamp;
454 mouse_data.device = -1;
458 case TOUCH_STATE_DOWN:
459 dx = mouse_data.x - sd->last_drag[0].x;
460 dy = mouse_data.y - sd->last_drag[0].y;
462 if ((abs(dx) > INIT_DRAG_THRESHOLD) || (abs(dy) > INIT_DRAG_THRESHOLD))
464 if (sd->animator_move)
466 ecore_animator_del(sd->animator_move);
467 sd->animator_move = NULL;
469 if (sd->animator_flick)
471 ecore_animator_del(sd->animator_flick);
472 sd->animator_flick = NULL;
474 _smart_set_last_drag(sd, 0, &mouse_data);
476 // last_down - location where the drag starts
477 // (which is different than fisrtDown)
478 _smart_set_last_down(sd, 0, &mouse_data);
479 _smart_enter_drag(sd);
483 case TOUCH_STATE_DRAG:
484 dx = mouse_data.x - sd->last_drag[0].x;
485 dy = mouse_data.y - sd->last_drag[0].y;
487 if ((abs(dx) > DRAG_THRESHOLD) || (abs(dy) > DRAG_THRESHOLD))
489 _smart_set_last_drag(sd, 0, &mouse_data);
490 _smart_save_move_history(sd, mouse_data.x, mouse_data.y, dx, dy);
494 case TOUCH_STATE_TWO_DOWN:
495 _smart_set_last_drag(sd, 0, &mouse_data);
497 sd->two_drag_mode = _smart_check_two_drag_mode(sd);
498 if (sd->two_drag_mode != TWO_DRAG_NONE)
500 DBG("<< sd->two_drag_mode [%d] >>\n", sd->two_drag_mode);
501 _smart_enter_two_drag(sd);
505 case TOUCH_STATE_TWO_DRAG:
506 _smart_set_last_drag(sd, 0, &mouse_data);
509 case TOUCH_STATE_THREE_DOWN:
510 _smart_set_last_drag(sd, 0, &mouse_data);
519 _smart_multi_down(void *data, Evas *e, Evas_Object *obj, void *ev)
524 if (!sd || sd->running == EINA_FALSE) return;
526 Evas_Event_Multi_Down *event = (Evas_Event_Multi_Down*)ev;
527 Mouse_Data mouse_data;
531 case TOUCH_STATE_DOWN:
532 case TOUCH_STATE_DRAG:
534 if (sd->numOfTouch == 1)
536 mouse_data.x = event->output.x;
537 mouse_data.y = event->output.y;
538 mouse_data.time = event->timestamp;
539 mouse_data.device = event->device;
540 _smart_set_first_down(sd, 1, &mouse_data);
541 _smart_set_last_down(sd, 1, &mouse_data);
542 _smart_set_last_drag(sd, 1, &mouse_data);
543 _smart_stop_animator_move(sd);
544 _smart_stop_animator_flick(sd);
545 _smart_stop_animator_two_move(sd);
546 _smart_enter_two_down(sd);
550 case TOUCH_STATE_TWO_DOWN:
551 case TOUCH_STATE_TWO_DRAG:
553 if (sd->numOfTouch == 2)
555 mouse_data.x = event->output.x;
556 mouse_data.y = event->output.y;
557 mouse_data.time = event->timestamp;
558 mouse_data.device = event->device;
559 _smart_set_first_down(sd, 2, &mouse_data);
560 _smart_set_last_down(sd, 2, &mouse_data);
561 _smart_set_last_drag(sd, 2, &mouse_data);
562 _smart_stop_animator_move(sd);
563 _smart_stop_animator_flick(sd);
564 _smart_stop_animator_two_move(sd);
565 _smart_enter_three_down(sd);
575 _smart_multi_up(void *data, Evas *e, Evas_Object *obj, void *ev)
578 Evas_Event_Multi_Up *event;
581 if (!sd || sd->running == EINA_FALSE) return;
583 event = (Evas_Event_Multi_Up*)ev;
587 case TOUCH_STATE_TWO_DOWN:
588 _smart_emit_two_tap(sd);
589 _smart_stop_all_timers(sd);
590 _smart_enter_none(sd);
593 case TOUCH_STATE_TWO_DRAG:
594 _smart_stop_animator_two_move(sd);
595 _smart_stop_all_timers(sd);
596 _smart_enter_none(sd);
599 case TOUCH_STATE_THREE_DOWN:
600 _smart_emit_three_tap(sd);
601 _smart_stop_all_timers(sd);
602 _smart_enter_none(sd);
606 _smart_stop_all_timers(sd);
607 _smart_enter_none(sd);
613 _smart_multi_move(void *data, Evas *e, Evas_Object *obj, void *ev)
616 Evas_Event_Multi_Move *event;
617 Mouse_Data mouse_data;
620 if (!sd || sd->running == EINA_FALSE) return;
622 event = (Evas_Event_Multi_Move*)ev;
623 mouse_data.x = event->cur.output.x;
624 mouse_data.y = event->cur.output.y;
625 mouse_data.time = event->timestamp;
626 mouse_data.device = event->device;
630 case TOUCH_STATE_TWO_DOWN:
631 if (sd->first_down[1].device == event->device)
633 _smart_set_last_drag(sd, 1, &mouse_data);
634 sd->two_drag_mode = _smart_check_two_drag_mode(sd);
635 if (sd->two_drag_mode != TWO_DRAG_NONE)
637 DBG("<< sd->two_drag_mode [%d] >>\n", sd->two_drag_mode);
638 _smart_enter_two_drag(sd);
643 case TOUCH_STATE_TWO_DRAG:
644 if (sd->first_down[1].device == event->device)
646 _smart_set_last_drag(sd, 1, &mouse_data);
650 case TOUCH_STATE_THREE_DOWN:
651 if (sd->first_down[1].device == event->device)
653 _smart_set_last_drag(sd, 1, &mouse_data);
655 else if (sd->first_down[2].device == event->device)
657 _smart_set_last_drag(sd, 2, &mouse_data);
668 _smart_animation_move(void *data)
675 DBG("<< animation_move >>\n");
676 // get the position here instead of mouse_move event
677 Evas *evas = evas_object_evas_get(sd->child_obj);
679 evas_pointer_canvas_xy_get(evas, &point.x, &point.y);
680 if (sd->is_one_drag_mode)
682 if (sd->one_drag_mode == ONE_DRAG_VERTICAL)
685 // first_down - location of mouse down
686 // last_down - location where the drag started
687 point.x = sd->last_down[0].x;
689 else if (sd->one_drag_mode == ONE_DRAG_HORIZONTAL)
691 point.y = sd->last_down[0].y;
694 evas_object_smart_callback_call(sd->child_obj, "one,move", &point);
695 return ECORE_CALLBACK_RENEW;
699 _smart_stop_animator_move(sd);
700 _smart_enter_none(sd);
701 return ECORE_CALLBACK_CANCEL;
706 _smart_animation_flick(void *data)
709 Flick_Data *flick_data;
712 flick_data = &(sd->flick_data);
714 if (flick_data && sd->child_obj)
717 float velocity = _smart_velocity_easeinoutcubic(flick_data->flick_index);
718 Evas_Coord dx = flick_data->avg_distance.x * velocity;
719 Evas_Coord dy = flick_data->avg_distance.y * velocity;
720 flick_data->flick_index++;
721 flick_data->last.x += dx;
722 flick_data->last.y += dy;
723 DBG("<< animation_flick |%d|%d|%f| >>\n", dx, dy, ecore_loop_time_get());
725 // stop flick animator
726 if (dx == 0 && dy == 0)
728 _smart_stop_animator_flick(sd);
729 _smart_enter_none(sd);
730 return ECORE_CALLBACK_CANCEL;
734 Evas_Coord_Point point;
735 point = flick_data->last;
736 if (sd->is_one_drag_mode)
738 if (sd->one_drag_mode == ONE_DRAG_VERTICAL)
740 point.x = sd->first_down[0].x;
742 else if (sd->one_drag_mode == ONE_DRAG_HORIZONTAL)
744 point.y = sd->first_down[0].y;
747 evas_object_smart_callback_call(sd->child_obj, "one,move", &point);
748 return ECORE_CALLBACK_RENEW;
753 _smart_stop_animator_flick(sd);
754 _smart_enter_none(sd);
755 return ECORE_CALLBACK_CANCEL;
760 _smart_animation_two_move(void *data)
768 _smart_emit_two_move(sd);
769 return ECORE_CALLBACK_RENEW;
773 _smart_stop_animator_two_move(sd);
774 _smart_enter_none(sd);
775 return ECORE_CALLBACK_CANCEL;
780 /* state switching */
782 _smart_enter_none(Smart_Data *sd)
785 sd->two_drag_mode = TWO_DRAG_NONE;
786 sd->state = TOUCH_STATE_NONE;
787 DBG("\nTOUCH_STATE_NONE\n");
791 _smart_enter_down(Smart_Data *sd)
794 sd->press_timer = ecore_timer_add(((double)PRESS_TIME)/1000.0, _smart_press_timer_handler, sd);
796 // set long press timer
797 sd->long_press_timer = ecore_timer_add(((double)LONG_HOLD_TIME)/1000.0, _smart_long_press_timer_handler, sd);
799 sd->state = TOUCH_STATE_DOWN;
800 DBG("\nTOUCH_STATE_DOWN\n");
804 _smart_enter_down_up(Smart_Data *sd, int downTime, int time)
806 // remove sd->press_timer and set new timer
807 int timerTime = RELEASE_TIME - (downTime - PRESS_TIME);
810 ecore_timer_del(sd->press_timer);
811 sd->press_timer = NULL;
812 sd->press_release_timer = ecore_timer_add(((double)timerTime)/1000.0, _smart_press_release_timer_handler, sd);
817 sd->release_timer = ecore_timer_add(((double)timerTime)/1000.0, _smart_release_timer_handler, sd);
820 if (sd->long_press_timer) // remove long press timer
822 ecore_timer_del(sd->long_press_timer);
823 sd->long_press_timer = NULL;
826 sd->state = TOUCH_STATE_DOWN_UP;
827 DBG("\nTOUCH_STATE_DOWN_UP\n");
831 _smart_enter_down_up_down(Smart_Data *sd)
833 if (sd->press_release_timer) // remove press_release_timer
835 ecore_timer_del(sd->press_release_timer);
836 sd->press_release_timer = NULL;
839 if (sd->release_timer) // remove ReleaseTimer
841 ecore_timer_del(sd->release_timer);
842 sd->release_timer = NULL;
845 sd->state = TOUCH_STATE_DOWN_UP_DOWN;
846 DBG("\nTOUCH_STATE_DOWN_UP_DOWN\n");
850 _smart_enter_hold(Smart_Data *sd)
852 sd->state = TOUCH_STATE_HOLD;
853 DBG("\nTOUCH_STATE_HOLD\n");
857 _smart_enter_drag(Smart_Data *sd)
859 if (sd->press_timer) // remove press_timer
861 ecore_timer_del(sd->press_timer);
862 sd->press_timer = NULL;
865 if (sd->press_release_timer) // remove press_release_timer
867 ecore_timer_del(sd->press_release_timer);
868 sd->press_release_timer = NULL;
871 if (sd->release_timer) // remove ReleaseTimer
873 ecore_timer_del(sd->release_timer);
874 sd->release_timer = NULL;
877 if (sd->long_press_timer) // remove long press timer
879 ecore_timer_del(sd->long_press_timer);
880 sd->long_press_timer = NULL;
885 if (sd->is_one_drag_mode)
887 sd->one_drag_mode = ONE_DRAG_NONE;
888 int abs_dx = abs(sd->first_down[0].x - sd->last_drag[0].x);
889 int abs_dy = abs(sd->first_down[0].y - sd->last_drag[0].y);
890 abs_dx = (abs_dx == 0) ? 1 : abs_dx;
891 DBG("<< abs_dx[%d], abs_dy[%d] >>\n\n", abs_dx, abs_dy);
892 float degree = (float)abs_dy / (float)abs_dx;
893 // more than 70 degree
894 if (degree > tan(70 * M_PI / 180))
896 sd->one_drag_mode = ONE_DRAG_VERTICAL;
898 // less than 20 degree
899 else if (degree < tan(20 * M_PI / 180))
901 sd->one_drag_mode = ONE_DRAG_HORIZONTAL;
905 point.x = sd->last_down[0].x;
906 point.y = sd->last_down[0].y;
907 evas_object_smart_callback_call(sd->child_obj, "one,move,start", &point);
909 // initialize flick variables
910 sd->last_move_history_index = -1;
911 sd->move_history_count = 0;
913 sd->animator_move = ecore_animator_add(_smart_animation_move, sd);
914 DBG("<< sd->animator_move >>\n");
915 sd->state = TOUCH_STATE_DRAG;
916 DBG("\nTOUCH_STATE_DRAG\n");
920 sd->state = TOUCH_STATE_NONE;
925 _smart_enter_two_down(Smart_Data *sd)
927 _smart_stop_all_timers(sd);
931 DBG("<< enter two down >>\n");
932 sd->state = TOUCH_STATE_TWO_DOWN;
933 _smart_emit_two_press(sd);
938 _smart_enter_two_drag(Smart_Data *sd)
942 DBG("<< sd->animator_two_move >>\n");
943 sd->state = TOUCH_STATE_TWO_DRAG;
944 _smart_emit_two_move_start(sd);
945 sd->animator_two_move = ecore_animator_add(_smart_animation_two_move, sd);
949 sd->state = TOUCH_STATE_NONE;
954 _smart_enter_three_down(Smart_Data *sd)
958 sd->state = TOUCH_STATE_THREE_DOWN;
959 _smart_emit_three_press(sd);
963 /* producing output events */
965 _smart_emit_press(Smart_Data *sd)
969 DBG("<< emit_press >>\n");
971 point.x = sd->last_down[0].x;
972 point.y = sd->last_down[0].y;
973 evas_object_smart_callback_call(sd->child_obj, "one,press", &point);
978 _smart_emit_tap(Smart_Data *sd)
982 DBG("<< emit_tap >>\n");
984 point.x = sd->last_down[0].x;
985 point.y = sd->last_down[0].y;
986 evas_object_smart_callback_call(sd->child_obj, "one,single,tap", &point);
991 _smart_emit_double_tap(Smart_Data *sd)
995 DBG("<< emit_double_tap >>\n");
997 point.x = sd->last_down[0].x;
998 point.y = sd->last_down[0].y;
999 evas_object_smart_callback_call(sd->child_obj, "one,double,tap", &point);
1004 _smart_emit_long_hold(Smart_Data *sd)
1008 DBG("<< emit_long_hold >>\n");
1010 point.x = sd->last_down[0].x;
1011 point.y = sd->last_down[0].y;
1012 evas_object_smart_callback_call(sd->child_obj, "one,long,press", &point);
1017 _smart_emit_release(Smart_Data *sd)
1021 DBG("<< emit_release >>\n");
1023 point.x = sd->last_down[0].x;
1024 point.y = sd->last_down[0].y;
1025 evas_object_smart_callback_call(sd->child_obj, "one,release", &point);
1030 _smart_emit_two_press(Smart_Data *sd)
1034 DBG("<< emit_two_press >>\n");
1035 Two_Mouse_Data two_mouse_data;
1036 two_mouse_data.first.x = sd->last_down[0].x;
1037 two_mouse_data.first.y = sd->last_down[0].y;
1038 two_mouse_data.second.x = sd->last_down[1].x;
1039 two_mouse_data.second.y = sd->last_down[1].y;
1040 two_mouse_data.mode = sd->two_drag_mode;
1041 evas_object_smart_callback_call(sd->child_obj, "two,press", &two_mouse_data);
1046 _smart_emit_two_tap(Smart_Data *sd)
1050 DBG("<< emit_two_tap >>\n");
1051 Two_Mouse_Data two_mouse_data;
1052 two_mouse_data.first.x = sd->last_down[0].x;
1053 two_mouse_data.first.y = sd->last_down[0].y;
1054 two_mouse_data.second.x = sd->last_down[1].x;
1055 two_mouse_data.second.y = sd->last_down[1].y;
1056 two_mouse_data.mode = sd->two_drag_mode;
1057 evas_object_smart_callback_call(sd->child_obj, "two,tap", &two_mouse_data);
1062 _smart_emit_two_move_start(Smart_Data *sd)
1066 DBG("<< emit_two_move_start >>\n");
1067 Two_Mouse_Data two_mouse_data;
1068 two_mouse_data.first.x = sd->last_drag[0].x;
1069 two_mouse_data.first.y = sd->last_drag[0].y;
1070 two_mouse_data.second.x = sd->last_drag[1].x;
1071 two_mouse_data.second.y = sd->last_drag[1].y;
1072 two_mouse_data.mode = sd->two_drag_mode;
1073 evas_object_smart_callback_call(sd->child_obj, "two,move,start", &two_mouse_data);
1078 _smart_emit_two_move(Smart_Data *sd)
1082 Two_Mouse_Data two_mouse_data;
1083 two_mouse_data.first.x = sd->last_drag[0].x;
1084 two_mouse_data.first.y = sd->last_drag[0].y;
1085 two_mouse_data.second.x = sd->last_drag[1].x;
1086 two_mouse_data.second.y = sd->last_drag[1].y;
1087 two_mouse_data.mode = sd->two_drag_mode;
1088 evas_object_smart_callback_call(sd->child_obj, "two,move", &two_mouse_data);
1093 _smart_emit_two_move_end(Smart_Data *sd)
1097 DBG("<< emit_two_move_end >>\n");
1098 Two_Mouse_Data two_mouse_data;
1099 two_mouse_data.first.x = sd->last_drag[0].x;
1100 two_mouse_data.first.y = sd->last_drag[0].y;
1101 two_mouse_data.second.x = sd->last_drag[1].x;
1102 two_mouse_data.second.y = sd->last_drag[1].y;
1103 two_mouse_data.mode = sd->two_drag_mode;
1104 evas_object_smart_callback_call(sd->child_obj, "two,move,end", &two_mouse_data);
1109 _smart_emit_three_press(Smart_Data *sd)
1113 DBG("<< emit_three_press >>\n");
1114 Three_Mouse_Data three_mouse_data;
1115 three_mouse_data.first.x = sd->last_drag[0].x;
1116 three_mouse_data.first.y = sd->last_drag[0].y;
1117 three_mouse_data.second.x = sd->last_drag[1].x;
1118 three_mouse_data.second.y = sd->last_drag[1].y;
1119 three_mouse_data.third.x = sd->last_drag[2].x;
1120 three_mouse_data.third.y = sd->last_drag[2].y;
1121 evas_object_smart_callback_call(sd->child_obj, "three,press", &three_mouse_data);
1126 _smart_emit_three_tap(Smart_Data *sd)
1130 DBG("<< emit_three_tap >>\n");
1131 Three_Mouse_Data three_mouse_data;
1132 three_mouse_data.first.x = sd->last_drag[0].x;
1133 three_mouse_data.first.y = sd->last_drag[0].y;
1134 three_mouse_data.second.x = sd->last_drag[1].x;
1135 three_mouse_data.second.y = sd->last_drag[1].y;
1136 three_mouse_data.third.x = sd->last_drag[2].x;
1137 three_mouse_data.third.y = sd->last_drag[2].y;
1138 evas_object_smart_callback_call(sd->child_obj, "three,tap", &three_mouse_data);
1142 /* timer event handling */
1144 _smart_press_timer_handler(void *data)
1149 _smart_emit_press(sd);
1150 sd->press_timer = NULL;
1151 return ECORE_CALLBACK_CANCEL;
1155 _smart_long_press_timer_handler(void *data)
1160 _smart_emit_long_hold(sd);
1161 _smart_enter_hold(sd);
1162 sd->long_press_timer = NULL;
1163 return ECORE_CALLBACK_CANCEL;
1167 _smart_release_timer_handler(void *data)
1172 _smart_emit_tap(sd);
1173 _smart_stop_all_timers(sd);
1174 _smart_enter_none(sd);
1175 sd->release_timer = NULL;
1176 return ECORE_CALLBACK_CANCEL;
1180 _smart_press_release_timer_handler(void *data)
1182 static int prevent_handler = 0;
1183 if (prevent_handler != 0) return ECORE_CALLBACK_CANCEL;
1184 prevent_handler = 1;
1188 _smart_emit_press(sd);
1189 _smart_emit_tap(sd);
1190 _smart_stop_all_timers(sd);
1191 _smart_enter_none(sd);
1192 sd->press_release_timer = NULL;
1193 prevent_handler = 0;
1194 return ECORE_CALLBACK_CANCEL;
1197 /* other functions */
1199 _smart_save_move_history(Smart_Data *sd, int x, int y, int dx, int dy)
1201 // save pan information to the pan history
1202 int index = (sd->last_move_history_index + 1) % MOVE_HISTORY_SIZE;
1203 sd->last_move_history_index = index;
1204 sd->move_history[index].dx = dx;
1205 sd->move_history[index].dy = dy;
1206 sd->move_history[index].time = ecore_time_get();
1207 sd->move_history_count++;
1211 _smart_start_flick(Smart_Data *sd)
1213 if (sd->animator_move)
1215 ecore_animator_del(sd->animator_move);
1216 DBG("<< stop_animator_move >>\n");
1217 sd->animator_move = NULL;
1220 // accumulate sd->move_history data
1224 int index = sd->last_move_history_index;
1225 int todo = sd->move_history_count > MOVE_HISTORY_SIZE ? MOVE_HISTORY_SIZE : sd->move_history_count;
1227 double endTime = (sd->move_history + index)->time;
1228 double startTime = endTime;
1229 for( ; todo > 0; todo--) {
1230 p = sd->move_history + index; // get one sd->move_history
1233 startTime = p->time;
1238 if ((endTime - startTime) > 0.2 && nSamples > 0)
1241 index = (index > 0) ? (index - 1) : (MOVE_HISTORY_SIZE - 1); // set index
1243 double totalTime = endTime - startTime;
1244 if (totalTime < DOUBLE_ERROR)
1247 // calculate average pan_dx and pan_dy (per 1 / DEFAULT_FRAMERATE ms)
1248 double temp = totalTime * DEFAULT_FRAMERATE;
1252 Flick_Data *flick_data = &sd->flick_data;
1253 flick_data->avg_distance.x = totalDx / temp;
1254 flick_data->avg_distance.y = totalDy / temp;
1256 // set max value for pan_dx and pan_dy
1257 int abs_pan_dx = abs(flick_data->avg_distance.x);
1258 int abs_pan_dy = abs(flick_data->avg_distance.y);
1259 if ((abs_pan_dx > MAX_MOVE_DISTANCE) && (abs_pan_dx > abs_pan_dy))
1261 flick_data->avg_distance.x = (flick_data->avg_distance.x > 0) ? MAX_MOVE_DISTANCE : -MAX_MOVE_DISTANCE;
1262 flick_data->avg_distance.y = flick_data->avg_distance.y * MAX_MOVE_DISTANCE / abs_pan_dx;
1265 else if ((abs_pan_dy > MAX_MOVE_DISTANCE) && (abs_pan_dy > abs_pan_dx))
1267 flick_data->avg_distance.y = (flick_data->avg_distance.y > 0) ? MAX_MOVE_DISTANCE : -MAX_MOVE_DISTANCE;
1268 flick_data->avg_distance.x = flick_data->avg_distance.x * MAX_MOVE_DISTANCE / abs_pan_dy;
1271 if (abs_pan_dx > FLICK_THRESHOLD || abs_pan_dy > FLICK_THRESHOLD)
1273 // set flick_data and start flick
1274 flick_data->last.x = sd->last_drag[0].x;
1275 flick_data->last.y = sd->last_drag[0].y;
1276 flick_data->flick_index = 0;
1277 sd->animator_flick = ecore_animator_add(_smart_animation_flick, sd);
1278 DBG("<< sd->animator_flick >>\n");
1283 point.x = sd->last_drag[0].x;
1284 point.y = sd->last_drag[0].y;
1285 evas_object_smart_callback_call(sd->child_obj, "one,move,end", &point);
1286 _smart_enter_none(sd);
1291 _smart_emit_release(sd);
1292 _smart_stop_all_timers(sd);
1293 _smart_enter_none(sd);
1298 _smart_stop_animator_move(Smart_Data *sd)
1300 if (sd->animator_move)
1302 ecore_animator_del(sd->animator_move);
1303 DBG("<< stop_animator_move >>\n");
1304 sd->animator_move = NULL;
1306 point.x = sd->last_drag[0].x;
1307 point.y = sd->last_drag[0].y;
1308 evas_object_smart_callback_call(sd->child_obj, "one,move,end", &point);
1313 _smart_stop_animator_flick(Smart_Data *sd)
1315 if (sd->animator_flick)
1317 ecore_animator_del(sd->animator_flick);
1318 DBG("<< stop_animator_flick >>\n");
1319 sd->animator_flick = NULL;
1320 Evas_Coord_Point point;
1321 point = sd->flick_data.last;
1322 evas_object_smart_callback_call(sd->child_obj, "one,move,end", &point);
1327 _smart_stop_animator_two_move(Smart_Data *sd)
1329 if (sd->animator_two_move)
1331 ecore_animator_del(sd->animator_two_move);
1332 DBG("<< stop_animator_two_move >>\n");
1333 sd->animator_two_move = NULL;
1334 _smart_emit_two_move_end(sd);
1338 static Two_Drag_Mode
1339 _smart_check_two_drag_mode(Smart_Data *sd)
1341 // get distance from press to current position
1342 int dx0 = sd->last_drag[0].x - sd->first_down[0].x;
1343 int dy0 = sd->last_drag[0].y - sd->first_down[0].y;
1344 int dx1 = sd->last_drag[1].x - sd->first_down[1].x;
1345 int dy1 = sd->last_drag[1].y - sd->first_down[1].y;
1350 if ((abs(dx1) >= MOVE_THRESHOLD) || (abs(dy1) >= MOVE_THRESHOLD))
1355 else if ((abs(dx0) >= MOVE_THRESHOLD) || (abs(dy0) >= MOVE_THRESHOLD))
1362 return TWO_DRAG_NONE;
1366 if ((abs(dx) > abs(dy)) && ((dx0 > 0 && dx1 > 0) || (dx0 < 0 && dx1 < 0)))
1368 dy = (dy == 0) ? 1 : dy;
1369 // less than 30 degree (1024/root(3) = 591)
1370 if (((abs(dy) << 10) / abs(dx)) < 591)
1372 return TWO_DRAG_HORIZONTAL;
1377 if ((abs(dy) > abs(dx)) && ((dy0 > 0 && dy1 > 0) || (dy0 < 0 && dy1 < 0)))
1379 dx = (dx == 0) ? 1 : dx;
1380 // more than 60 degree (1024 * root(3)/1 = 1773)
1381 if (((abs(dy) << 10) / abs(dx)) > 1773)
1383 return TWO_DRAG_VERTICAL;
1388 int distanceX = abs(abs(sd->first_down[0].x - sd->first_down[1].x)
1389 - abs(sd->last_drag[0].x - sd->last_drag[1].x));
1390 int distanceY = abs(abs(sd->first_down[0].y - sd->first_down[1].y)
1391 - abs(sd->last_drag[0].y - sd->last_drag[1].y));
1392 if ((distanceX > FINGER_DISTANCE) || (distanceY > FINGER_DISTANCE))
1394 return TWO_DRAG_PINCH;
1397 return TWO_DRAG_NONE;
1401 _smart_set_first_down(Smart_Data *sd, int index, Mouse_Data *data)
1403 if (index > N_FINGER)
1408 if ((sd->screen_angle == 270) && (index > 0))
1410 sd->first_down[index].x = data->y;
1411 sd->first_down[index].y = data->x;
1412 sd->first_down[index].time = data->time;
1413 sd->first_down[index].device = data->device;
1417 sd->first_down[index].x = data->x;
1418 sd->first_down[index].y = data->y;
1419 sd->first_down[index].time = data->time;
1420 sd->first_down[index].device = data->device;
1425 _smart_set_last_down(Smart_Data *sd, int index, Mouse_Data *data)
1427 if (index > N_FINGER)
1432 if ((sd->screen_angle == 270) && (index > 0))
1434 sd->last_down[index].x = data->y;
1435 sd->last_down[index].y = data->x;
1436 sd->last_down[index].time = data->time;
1437 sd->last_down[index].device = data->device;
1441 sd->last_down[index].x = data->x;
1442 sd->last_down[index].y = data->y;
1443 sd->last_down[index].time = data->time;
1444 sd->last_down[index].device = data->device;
1449 _smart_set_last_drag(Smart_Data *sd, int index, Mouse_Data *data)
1451 if (index > N_FINGER)
1456 if ((sd->screen_angle == 270) && (index > 0))
1458 sd->last_drag[index].x = data->y;
1459 sd->last_drag[index].y = data->x;
1460 sd->last_drag[index].time = data->time;
1461 sd->last_drag[index].device = data->device;
1465 sd->last_drag[index].x = data->x;
1466 sd->last_drag[index].y = data->y;
1467 sd->last_drag[index].time = data->time;
1468 sd->last_drag[index].device = data->device;
1473 _smart_stop_all_timers(Smart_Data *sd)
1475 if (sd->press_timer) // remove sd->press_timer
1477 ecore_timer_del(sd->press_timer);
1478 sd->press_timer = NULL;
1481 if (sd->long_press_timer) // remove long press timer
1483 ecore_timer_del(sd->long_press_timer);
1484 sd->long_press_timer = NULL;
1487 if (sd->release_timer) // remove release timer
1489 ecore_timer_del(sd->release_timer);
1490 sd->release_timer = NULL;
1493 if (sd->press_release_timer) // remove pressRelease timer
1495 ecore_timer_del(sd->press_release_timer);
1496 sd->press_release_timer = NULL;
1501 _smart_add(Evas_Object *obj)
1505 sd = calloc(1, sizeof(Smart_Data));
1507 memset((void *)sd, 0x00, sizeof(Smart_Data));
1509 sd->smart_obj = obj;
1511 // set default framerate
1512 ecore_animator_frametime_set(1.0 / DEFAULT_FRAMERATE);
1514 evas_object_smart_data_set(obj, sd);
1518 _smart_del(Evas_Object *obj)
1523 if (sd->press_timer)
1524 ecore_timer_del(sd->press_timer);
1526 if (sd->long_press_timer)
1527 ecore_timer_del(sd->long_press_timer);
1529 if (sd->release_timer)
1530 ecore_timer_del(sd->release_timer);
1532 if (sd->press_release_timer)
1533 ecore_timer_del(sd->press_release_timer);
1535 if (sd->animator_move)
1536 ecore_animator_del(sd->animator_move);
1538 if (sd->animator_flick)
1539 ecore_animator_del(sd->animator_flick);
1541 if (sd->animator_two_move)
1542 ecore_animator_del(sd->animator_two_move);
1546 evas_object_event_callback_del(sd->child_obj, EVAS_CALLBACK_MOUSE_DOWN, _smart_mouse_down);
1547 evas_object_event_callback_del(sd->child_obj, EVAS_CALLBACK_MOUSE_UP, _smart_mouse_up);
1548 evas_object_event_callback_del(sd->child_obj, EVAS_CALLBACK_MOUSE_MOVE, _smart_mouse_move);
1549 evas_object_event_callback_del(sd->child_obj, EVAS_CALLBACK_MULTI_DOWN, _smart_multi_down);
1550 evas_object_event_callback_del(sd->child_obj, EVAS_CALLBACK_MULTI_UP, _smart_multi_up);
1551 evas_object_event_callback_del(sd->child_obj, EVAS_CALLBACK_MULTI_MOVE, _smart_multi_move);
1563 static const Evas_Smart_Class sc =
1566 EVAS_SMART_CLASS_VERSION,
1584 _smart = evas_smart_class_new(&sc);