X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Flib%2Felm_gesture_layer.c;h=68b7758a1da019ff6e4eef5237d87796fa39db4c;hb=3c28f3e6960438ede0b1d7e1a3b22c3c8bcbe796;hp=44df48456d61ec5edc72bbc6c80e157496846b23;hpb=6133b896f07521bd95f122201d5632d5a9fe094b;p=framework%2Fuifw%2Felementary.git diff --git a/src/lib/elm_gesture_layer.c b/src/lib/elm_gesture_layer.c index 44df484..68b7758 100644 --- a/src/lib/elm_gesture_layer.c +++ b/src/lib/elm_gesture_layer.c @@ -6,10 +6,13 @@ #define ELM_MOUSE_DEVICE 0 /* ELM_GESTURE_NEGATIVE_ANGLE - magic number says we didn't compute this yet */ #define ELM_GESTURE_NEGATIVE_ANGLE (-1.0) /* Magic number */ +#define ELM_GESTURE_MOMENTUM_DELAY 25 #define ELM_GESTURE_MOMENTUM_TIMEOUT 50 #define ELM_GESTURE_MULTI_TIMEOUT 50 #define ELM_GESTURE_MINIMUM_MOMENTUM 0.001 +#define ELM_GESTURE_TAP_TIMEOUT 0.2 + /* Some Trigo values */ #define RAD_90DEG M_PI_2 #define RAD_180DEG M_PI @@ -17,6 +20,9 @@ #define RAD_360DEG (M_PI * 2) /* #define DEBUG_GESTURE_LAYER 1 */ +#define RAD2DEG(x) ((x) * 57.295779513) +#define DEG2RAD(x) ((x) / 57.295779513) + static void * _glayer_bufdup(void *buf, size_t size) { @@ -71,7 +77,7 @@ struct _Gesture_Info Evas_Object *obj; void *data; /**< Holds gesture intemidiate processing data */ Func_Data fn[ELM_GESTURE_STATE_ABORT + 1]; /**< Callback info for states */ - Elm_Gesture_Types g_type; /**< gesture type */ + Elm_Gesture_Type g_type; /**< gesture type */ Elm_Gesture_State state; /**< gesture state */ void *info; /**< Data for the state callback */ Eina_Bool test; /**< if true this gesture should be tested on input */ @@ -209,6 +215,7 @@ struct _Zoom_Type Evas_Coord zoom_base; /* Holds gap between fingers on zoom-start */ Evas_Coord zoom_distance_tolerance; unsigned int m_st_tm; /* momentum start time */ + unsigned int m_prev_tm; /* momentum prev time */ int dir; /* Direction: 1=zoom-in, (-1)=zoom-out */ double m_base; /* zoom value when momentum starts */ double next_step; @@ -265,7 +272,7 @@ static Eina_Bool _event_history_clear(Evas_Object *obj); static void _reset_states(Widget_Data *wd); static void _key_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info); static void _key_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info); -static void _zoom_with_wheel_test(Evas_Object *obj, void *event_info, Evas_Callback_Type event_type, Elm_Gesture_Types g_type); +static void _zoom_with_wheel_test(Evas_Object *obj, void *event_info, Evas_Callback_Type event_type, Elm_Gesture_Type g_type); static void _mouse_wheel(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info); static void _mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info); static void _mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info); @@ -403,10 +410,12 @@ consume_event(Widget_Data *wd, void *event_info, { /* Mark EVAS_EVENT_FLAG_ON_HOLD on events that are used by gesture layer */ /* ev_flags != EVAS_EVENT_FLAG_NONE means target used event and g-layer */ /* should not refeed this event. */ - if(!event_info) + if (!event_info) return; /* This happens when restarting gestures */ - if ((ev_flags) || (!wd->repeat_events)) + if (!wd->repeat_events) ev_flags |= EVAS_EVENT_FLAG_ON_HOLD; + + if (ev_flags) { switch(event_type) { @@ -581,19 +590,19 @@ _clear_if_finished(Evas_Object *obj) } static Eina_Bool -_inside(Evas_Coord x1, Evas_Coord y1, Evas_Coord x2, Evas_Coord y2) +_inside(Evas_Coord xx1, Evas_Coord yy1, Evas_Coord xx2, Evas_Coord yy2) { - int w = elm_finger_size_get() >> 1; /* Finger size devided by 2 */ - if (x1 < (x2 - w)) + int w = _elm_config->finger_size >> 1; /* Finger size devided by 2 */ + if (xx1 < (xx2 - w)) return EINA_FALSE; - if (x1 > (x2 + w)) + if (xx1 > (xx2 + w)) return EINA_FALSE; - if (y1 < (y2 - w)) + if (yy1 < (yy2 - w)) return EINA_FALSE; - if (y1 > (y2 + w)) + if (yy1 > (yy2 + w)) return EINA_FALSE; return EINA_TRUE; @@ -610,10 +619,15 @@ _tap_gestures_test_reset(Gesture_Info *gesture) return; Widget_Data *wd = elm_widget_data_get(gesture->obj); - wd->dbl_timeout = NULL; Eina_List *data; Pointer_Event *pe; + if (wd->dbl_timeout) + { + ecore_timer_del(wd->dbl_timeout); + wd->dbl_timeout = NULL; + } + if (!gesture->data) return; @@ -641,10 +655,14 @@ _n_long_tap_test_reset(Gesture_Info *gesture) Eina_List *l; Pointer_Event *p; EINA_LIST_FOREACH(st->touched, l, p) - free(p); + free(p); eina_list_free(st->touched); - if (st->timeout) ecore_timer_del(st->timeout); + if (st->timeout) + { + ecore_timer_del(st->timeout); + st->timeout = NULL; + } memset(gesture->data, 0, sizeof(Long_Tap_Type)); } @@ -851,9 +869,9 @@ _add_device_pending(Eina_List *list, void *event, Evas_Callback_Type event_type) } if (!eina_list_search_unsorted_list(list, device_in_pending_list, - (intptr_t*) device)) + (void *)(intptr_t)device)) { - return eina_list_append(list, (intptr_t*) device); + return eina_list_append(list, (void *)(intptr_t)device); } return list; @@ -881,7 +899,7 @@ _device_is_pending(Eina_List *list, void *event, Evas_Callback_Type event_type) } return eina_list_search_unsorted_list(list, device_in_pending_list, - (intptr_t *) device); + (void *)(intptr_t)device); } /** @@ -908,7 +926,7 @@ _event_history_clear(Evas_Object *obj) Gesture_Info *p; Evas *e = evas_object_evas_get(obj); Eina_Bool gesture_found = EINA_FALSE; - for (i = ELM_GESTURE_FIRST ; i < ELM_GESTURE_LAST; i++) + for (i = ELM_GESTURE_FIRST; i < ELM_GESTURE_LAST; i++) { p = wd->gesture[i]; if (p) @@ -1065,7 +1083,7 @@ _del_hook(Evas_Object *obj) Pointer_Event *data; EINA_LIST_FREE(wd->touched, data) - free(data); + free(data); if (!elm_widget_disabled_get(obj)) _unregister_callbacks(obj); @@ -1114,7 +1132,6 @@ compare_pe_device(const void *data1, const void *data2) (pe1->event_type != EVAS_CALLBACK_MOUSE_DOWN)) return 1; - if (pe1->device == pe2->device) return 0; else if (pe1->device < pe2->device) @@ -1154,32 +1171,55 @@ _record_pointer_event(Taps_Type *st, Eina_List *pe_list, Pointer_Event *pe, /** * @internal * - * This function sets state a tap-gesture to END or ABORT + * This function checks if the tap gesture is done. * * @param data gesture info pointer + * @return EINA_TRUE if it is done. * * @ingroup Elm_Gesture_Layer */ -static void -_tap_gesture_finish(void *data) -{ /* This function will test each tap gesture when timer expires */ - Gesture_Info *gesture = data; - Elm_Gesture_State s = ELM_GESTURE_STATE_END; +static Eina_Bool +_tap_gesture_check_finish(Gesture_Info *gesture) +{ /* Here we check if taps-gesture was completed successfuly */ /* Count how many taps were recieved on each device then */ /* determine if it matches n_taps_needed defined on START */ Taps_Type *st = gesture->data; Eina_List *l; Eina_List *pe_list; + if (!st || !st->l) return EINA_FALSE; EINA_LIST_FOREACH(st->l, l, pe_list) { if (eina_list_count(pe_list) != st->n_taps_needed) { /* No match taps number on device, ABORT */ - s = ELM_GESTURE_STATE_ABORT; - break; + return EINA_FALSE; } } + return EINA_TRUE; +} + +/** + * @internal + * + * This function sets state a tap-gesture to END or ABORT + * + * @param data gesture info pointer + * + * @ingroup Elm_Gesture_Layer + */ +static void +_tap_gesture_finish(void *data) +{ /* This function will test each tap gesture when timer expires */ + Elm_Gesture_State s = ELM_GESTURE_STATE_ABORT; + Gesture_Info *gesture = data; + Taps_Type *st = gesture->data; + + if (_tap_gesture_check_finish(gesture)) + { + s = ELM_GESTURE_STATE_END; + } + st->info.n = eina_list_count(st->l); _set_state(gesture, s, gesture->info, EINA_FALSE); _tap_gestures_test_reset(gesture); @@ -1202,13 +1242,13 @@ _multi_tap_timeout(void *data) if (!wd) return EINA_FALSE; if (IS_TESTED(ELM_GESTURE_N_TAPS)) - _tap_gesture_finish(wd->gesture[ELM_GESTURE_N_TAPS]); + _tap_gesture_finish(wd->gesture[ELM_GESTURE_N_TAPS]); if (IS_TESTED(ELM_GESTURE_N_DOUBLE_TAPS)) - _tap_gesture_finish(wd->gesture[ELM_GESTURE_N_DOUBLE_TAPS]); + _tap_gesture_finish(wd->gesture[ELM_GESTURE_N_DOUBLE_TAPS]); if (IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS)) - _tap_gesture_finish(wd->gesture[ELM_GESTURE_N_TRIPLE_TAPS]); + _tap_gesture_finish(wd->gesture[ELM_GESTURE_N_TRIPLE_TAPS]); _clear_if_finished(data); wd->dbl_timeout = NULL; @@ -1242,7 +1282,7 @@ _long_tap_timeout(void *data) /** * @internal * - * This function checks if a tap gesture should start + * This function checks the state of a tap gesture. * * @param wd Gesture Layer Widget Data. * @param pe The recent input event as stored in pe struct. @@ -1251,15 +1291,16 @@ _long_tap_timeout(void *data) * @param gesture what gesture is tested * @param how many taps for this gesture (1, 2 or 3) * - * @return Flag to determine if we need to set a timer for finish - * * @ingroup Elm_Gesture_Layer */ -static Eina_Bool -_tap_gesture_start(Widget_Data *wd, Pointer_Event *pe, +static void +_tap_gesture_test(Widget_Data *wd, Pointer_Event *pe, void *event_info, Evas_Callback_Type event_type, Gesture_Info *gesture, int taps) { /* Here we fill Tap struct */ + if (!pe) + return; + Taps_Type *st = gesture->data; if (!st) { /* Allocated once on first time */ @@ -1285,10 +1326,20 @@ _tap_gesture_start(Widget_Data *wd, Pointer_Event *pe, &st->info, EINA_FALSE); consume_event(wd, event_info, event_type, ev_flag); - return EINA_FALSE; + return; } pe_list = _record_pointer_event(st, pe_list, pe, wd, event_info, event_type); + if (!wd->dbl_timeout) + { + wd->dbl_timeout = ecore_timer_add(ELM_GESTURE_TAP_TIMEOUT, + _multi_tap_timeout, gesture->obj); + } + else + { + ecore_timer_reset(wd->dbl_timeout); + } + if ((pe->device == 0) && (eina_list_count(pe_list) == 1)) { /* This is the first mouse down we got */ ev_flag = _set_state(gesture, ELM_GESTURE_STATE_START, @@ -1297,7 +1348,13 @@ _tap_gesture_start(Widget_Data *wd, Pointer_Event *pe, st->n_taps_needed = taps * 2; /* count DOWN and UP */ - return EINA_TRUE; + return; + } + else if (eina_list_count(pe_list) > st->n_taps_needed) + { + /* If we arleady got too many touches for this gesture. */ + ev_flag = _set_state(gesture, ELM_GESTURE_STATE_ABORT, + &st->info, EINA_FALSE); } break; @@ -1306,9 +1363,23 @@ _tap_gesture_start(Widget_Data *wd, Pointer_Event *pe, case EVAS_CALLBACK_MOUSE_UP: pe_list = eina_list_search_unsorted(st->l, compare_pe_device, pe); if (!pe_list) - return EINA_FALSE; + return; pe_list = _record_pointer_event(st, pe_list, pe, wd, event_info, event_type); + + if (((gesture->g_type == ELM_GESTURE_N_TAPS) && + !IS_TESTED(ELM_GESTURE_N_DOUBLE_TAPS) && + !IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS)) || + ((gesture->g_type == ELM_GESTURE_N_DOUBLE_TAPS) && + !IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS))) + { + if (_tap_gesture_check_finish(gesture)) + { + _tap_gesture_finish(gesture); + return; + } + } + break; case EVAS_CALLBACK_MULTI_MOVE: @@ -1329,52 +1400,7 @@ _tap_gesture_start(Widget_Data *wd, Pointer_Event *pe, break; default: - return EINA_FALSE; - } - - return EINA_FALSE; -} - - -/** - * @internal - * - * This function checks all click/tap and double/triple taps - * - * @param obj The gesture-layer object. - * @param pe The recent input event as stored in pe struct. - * @param event_info Original input event pointer. - * @param event_type Type of original input event. - * - * @ingroup Elm_Gesture_Layer - */ -static void -_tap_gestures_test(Evas_Object *obj, Pointer_Event *pe, - void *event_info, Evas_Callback_Type event_type) -{ /* Here we fill Recent_Taps struct and fire-up click/tap timers */ - Eina_Bool need_timer = EINA_FALSE; - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return; - - if (!pe) /* this happens when unhandled event arrived */ - return; /* see _make_pointer_event function */ - - if (IS_TESTED(ELM_GESTURE_N_TAPS)) - need_timer |= _tap_gesture_start(wd, pe, event_info, event_type, - wd->gesture[ELM_GESTURE_N_TAPS], 1); - - if (IS_TESTED(ELM_GESTURE_N_DOUBLE_TAPS)) - need_timer |= _tap_gesture_start(wd, pe, event_info, event_type, - wd->gesture[ELM_GESTURE_N_DOUBLE_TAPS], 2); - - if (IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS)) - need_timer |= _tap_gesture_start(wd, pe, event_info, event_type, - wd->gesture[ELM_GESTURE_N_TRIPLE_TAPS], 3); - - if ((need_timer) && (!wd->dbl_timeout)) - { /* Set a timer to finish these gestures */ - wd->dbl_timeout = ecore_timer_add(0.4, _multi_tap_timeout, - obj); + return ; } } @@ -1392,7 +1418,7 @@ static void _compute_taps_center(Long_Tap_Type *st, Evas_Coord *x_out, Evas_Coord *y_out, Pointer_Event *pe) { - if(!eina_list_count(st->touched)) + if (!eina_list_count(st->touched)) return; Eina_List *l; @@ -1433,7 +1459,7 @@ _compute_taps_center(Long_Tap_Type *st, static void _n_long_tap_test(Evas_Object *obj, Pointer_Event *pe, void *event_info, Evas_Callback_Type event_type, - Elm_Gesture_Types g_type) + Elm_Gesture_Type g_type) { /* Here we fill Recent_Taps struct and fire-up click/tap timers */ Widget_Data *wd = elm_widget_data_get(obj); if (!wd) return; @@ -1516,7 +1542,7 @@ _n_long_tap_test(Evas_Object *obj, Pointer_Event *pe, case EVAS_CALLBACK_MULTI_MOVE: case EVAS_CALLBACK_MOUSE_MOVE: - if(st->info.n && + if (st->info.n && ((gesture->state == ELM_GESTURE_STATE_START) || (gesture->state == ELM_GESTURE_STATE_MOVE))) { /* Report MOVE only if STARTED */ @@ -1562,13 +1588,14 @@ _n_long_tap_test(Evas_Object *obj, Pointer_Event *pe, * @ingroup Elm_Gesture_Layer */ static void -_set_momentum(Elm_Gesture_Momentum_Info *momentum, Evas_Coord x1, Evas_Coord y1, - Evas_Coord x2, Evas_Coord y2, unsigned int t1x, unsigned int t1y, - unsigned int t2) +_set_momentum(Elm_Gesture_Momentum_Info *momentum, + Evas_Coord xx1, Evas_Coord yy1, + Evas_Coord xx2, Evas_Coord yy2, + unsigned int t1x, unsigned int t1y, unsigned int t2) { Evas_Coord velx = 0, vely = 0, vel; - Evas_Coord dx = x2 - x1; - Evas_Coord dy = y2 - y1; + Evas_Coord dx = xx2 - xx1; + Evas_Coord dy = yy2 - yy1; int dtx = t2 - t1x; int dty = t2 - t1y; if (dtx > 0) @@ -1602,65 +1629,57 @@ _set_momentum(Elm_Gesture_Momentum_Info *momentum, Evas_Coord x1, Evas_Coord y1, * @param x2 second finger x location. * @param y2 second finger y location. * - * @return angle of the line between (x1,y1), (x2,y2) in Radians. + * @return angle of the line between (x1,y1), (x2,y2) in Deg. + * Angles now are given in DEG, not RAD. + * ZERO angle at 12-oclock, growing clockwise. * * @ingroup Elm_Gesture_Layer */ static double -get_angle(Evas_Coord x1, Evas_Coord y1, Evas_Coord x2, Evas_Coord y2) +get_angle(Evas_Coord xx1, Evas_Coord yy1, Evas_Coord xx2, Evas_Coord yy2) { - double a, xx, yy; - xx = fabs(x2 - x1); - yy = fabs(y2 - y1); + double a, xx, yy, rt = (-1); + xx = fabs(xx2 - xx1); + yy = fabs(yy2 - yy1); - if (((int) xx) && ((int) yy)) + if (((int)xx) && ((int)yy)) { - a = atan(yy / xx); - if (x1 < x2) + rt = a = RAD2DEG(atan(yy / xx)); + if (xx1 < xx2) { - if (y1 < y2) - { - return RAD_360DEG - a; - } - else - { - return (a); - } + if (yy1 < yy2) rt = 360 - a; + else rt = a; } else { - if (y1 < y2) - { - return RAD_180DEG + a; - } - else - { - return RAD_180DEG - a; - } + if (yy1 < yy2) rt = 180 + a; + else rt = 180 - a; } } - if (((int) xx)) - { /* Horizontal line */ - if (x2 < x1) - { - return RAD_180DEG; + if (rt < 0) + { /* Do this only if rt is not set */ + if (((int)xx)) + { /* Horizontal line */ + if (xx2 < xx1) rt = 180; + else rt = 0.0; } else - { - return 0.0; + { /* Vertical line */ + if (yy2 < yy1) rt = 90; + else rt = 270; } } - /* Vertical line */ - if (y2 < y1) - { - return RAD_90DEG; - } - else - { - return RAD_270DEG; - } + /* Now we want to change from: + * 90 0 + * original circle 180 0 We want: 270 90 + * 270 180 + */ + rt = 450 - rt; + if (rt >= 360) rt -= 360; + + return rt; } /** @@ -1679,25 +1698,22 @@ get_angle(Evas_Coord x1, Evas_Coord y1, Evas_Coord x2, Evas_Coord y2) * @ingroup Elm_Gesture_Layer */ static void -get_vector(Evas_Coord x1, Evas_Coord y1, Evas_Coord x2, Evas_Coord y2, - Evas_Coord *l, double *a) +get_vector(Evas_Coord xx1, Evas_Coord yy1, Evas_Coord xx2, Evas_Coord yy2, + Evas_Coord *l, double *a) { Evas_Coord xx, yy; - xx = x2 - x1; - yy = y2 - y1; - *l = (Evas_Coord) sqrt(xx*xx + yy*yy); - *a = get_angle(x1, y1, x2, y2); + xx = xx2 - xx1; + yy = yy2 - yy1; + *l = (Evas_Coord) sqrt((xx * xx) + (yy * yy)); + *a = get_angle(xx1, yy1, xx2, yy2); } static int -_get_direction(Evas_Coord x1, Evas_Coord x2) +_get_direction(Evas_Coord xx1, Evas_Coord xx2) { - if (x1 == x2) - return 0; - else if (x2 < x1) - return -1; - else - return 1; + if (xx2 < xx1) return -1; + if (xx2 > xx1) return 1; + return 0; } /** * @internal @@ -1713,8 +1729,8 @@ _get_direction(Evas_Coord x1, Evas_Coord x2) */ static void _momentum_test(Evas_Object *obj, Pointer_Event *pe, - void *event_info, Evas_Callback_Type event_type, - Elm_Gesture_Types g_type) + void *event_info, Evas_Callback_Type event_type, + Elm_Gesture_Type g_type) { Widget_Data *wd = elm_widget_data_get(obj); if (!wd) return; @@ -1764,6 +1780,7 @@ _momentum_test(Evas_Object *obj, Pointer_Event *pe, if ((st->info.n) && (st->info.n < cnt)) state_to_report = ELM_GESTURE_STATE_ABORT; + if (st->info.n < cnt) st->info.n = cnt; @@ -1796,10 +1813,21 @@ _momentum_test(Evas_Object *obj, Pointer_Event *pe, } - /* ABORT gesture if got DOWN or MOVE event after UP+timeout */ - if ((st->t_up) && - ((st->t_up + ELM_GESTURE_MULTI_TIMEOUT) < pe_local.timestamp)) - state_to_report = ELM_GESTURE_STATE_ABORT; + if (st->t_up) + { + Eina_Bool force = EINA_TRUE; /* for move state */ + if ((st->t_up + ELM_GESTURE_MULTI_TIMEOUT) < pe_local.timestamp) + { /* ABORT if got DOWN or MOVE event after UP+timeout */ + state_to_report = ELM_GESTURE_STATE_ABORT; + force = EINA_FALSE; + } + + /* We report state but don't compute momentum now */ + ev_flag = _set_state(gesture, state_to_report, &st->info, + force); + consume_event(wd, event_info, event_type, ev_flag); + return; /* Stop computing when user remove finger */ + } if ((pe_local.timestamp - ELM_GESTURE_MOMENTUM_TIMEOUT) > st->t_end) { /* Too long of a wait, reset all values */ @@ -1813,16 +1841,16 @@ _momentum_test(Evas_Object *obj, Pointer_Event *pe, else { int xdir, ydir; - xdir = _get_direction(st->line_st.x, pe_local.x); - ydir = _get_direction(st->line_st.y, pe_local.y); - if (!xdir || (xdir == (-st->xdir))) + xdir = _get_direction(st->line_end.x, pe_local.x); + ydir = _get_direction(st->line_end.y, pe_local.y); + if (xdir && (xdir != st->xdir)) { st->line_st.x = st->line_end.x; st->info.tx = st->t_st_x = st->t_end; st->xdir = xdir; } - if (!ydir || (ydir == (-st->ydir))) + if (ydir && (ydir != st->ydir)) { st->line_st.y = st->line_end.y; st->info.ty = st->t_st_y = st->t_end; @@ -1833,8 +1861,10 @@ _momentum_test(Evas_Object *obj, Pointer_Event *pe, st->info.x2 = st->line_end.x = pe_local.x; st->info.y2 = st->line_end.y = pe_local.y; st->t_end = pe_local.timestamp; - _set_momentum(&st->info, st->line_st.x, st->line_st.y, pe_local.x, pe_local.y, - st->t_st_x, st->t_st_y, pe_local.timestamp); + _set_momentum(&st->info, st->line_st.x, st->line_st.y, + pe_local.x, pe_local.y, st->t_st_x, st->t_st_y, + pe_local.timestamp); + ev_flag = _set_state(gesture, state_to_report, &st->info, EINA_TRUE); consume_event(wd, event_info, event_type, ev_flag); @@ -1862,9 +1892,6 @@ _momentum_test(Evas_Object *obj, Pointer_Event *pe, st->line_end.y = pe_local.y; st->t_end = pe_local.timestamp; - _set_momentum(&st->info, st->line_st.x, st->line_st.y, pe_local.x, pe_local.y, - st->t_st_x, st->t_st_y, pe_local.timestamp); - if ((fabs(st->info.mx) > ELM_GESTURE_MINIMUM_MOMENTUM) || (fabs(st->info.my) > ELM_GESTURE_MINIMUM_MOMENTUM)) state_to_report = ELM_GESTURE_STATE_END; @@ -1975,7 +2002,7 @@ _single_line_process(Elm_Gesture_Line_Info *info, Line_Data *st, */ static void _n_line_test(Evas_Object *obj, Pointer_Event *pe, void *event_info, - Evas_Callback_Type event_type, Elm_Gesture_Types g_type) + Evas_Callback_Type event_type, Elm_Gesture_Type g_type) { if (!pe) return; @@ -2048,9 +2075,9 @@ _n_line_test(Evas_Object *obj, Pointer_Event *pe, void *event_info, { /* if line direction was set, we test if broke tolerance */ double a = fabs(angle - line->line_angle); - double d = (tan(a)) * line->line_length; /* Distance from line */ + double d = (tan(DEG2RAD(a))) * line->line_length; /* Distance from line */ #if defined(DEBUG_GESTURE_LAYER) - printf("%s a=<%f> d=<%f>\n", __func__, (a * 57.295779513), d); + printf("%s a=<%f> d=<%f>\n", __func__, a, d); #endif if ((d > wd->line_distance_tolerance) || (a > wd->line_angular_tolerance)) { /* Broke tolerance: abort line and start a new one */ @@ -2160,7 +2187,7 @@ _n_line_test(Evas_Object *obj, Pointer_Event *pe, void *event_info, /* We report ABORT if lines length are NOT matching when fingers are up */ - if ((longest_line_len - shortest_line_len) > (elm_finger_size_get()*2)) + if ((longest_line_len - shortest_line_len) > (_elm_config->finger_size * 2)) { ev_flag = _set_state(gesture, ELM_GESTURE_STATE_ABORT, &st->info, EINA_FALSE); @@ -2251,24 +2278,24 @@ rotation_broke_tolerance(Rotate_Type *st) if (low < 0) { - low += RAD_180DEG; - high += RAD_180DEG; + low += 180; + high += 180; - if (t < RAD_180DEG) - t += RAD_180DEG; + if (t < 180) + t += 180; else - t -= RAD_180DEG; + t -= 180; } - if (high > RAD_360DEG) + if (high > 360) { - low -= RAD_180DEG; - high -= RAD_180DEG; + low -= 180; + high -= 180; - if (t < RAD_180DEG) - t += RAD_180DEG; + if (t < 180) + t += 180; else - t -= RAD_180DEG; + t -= 180; } #if defined(DEBUG_GESTURE_LAYER) @@ -2302,13 +2329,14 @@ rotation_broke_tolerance(Rotate_Type *st) * @ingroup Elm_Gesture_Layer */ static Evas_Coord -get_finger_gap_length(Evas_Coord x1, Evas_Coord y1, Evas_Coord x2, - Evas_Coord y2, Evas_Coord *x, Evas_Coord *y) +get_finger_gap_length(Evas_Coord xx1, Evas_Coord yy1, + Evas_Coord xx2, Evas_Coord yy2, + Evas_Coord *x, Evas_Coord *y) { double a, b, xx, yy, gap; - xx = fabs(x2 - x1); - yy = fabs(y2 - y1); - gap = sqrt(xx*xx + yy*yy); + xx = fabs(xx2 - xx1); + yy = fabs(yy2 - yy1); + gap = sqrt((xx * xx) + (yy * yy)); /* START - Compute zoom center point */ /* The triangle defined as follows: @@ -2321,7 +2349,7 @@ get_finger_gap_length(Evas_Coord x1, Evas_Coord y1, Evas_Coord x2, * b * http://en.wikipedia.org/wiki/Trigonometric_functions *************************************/ - if (((int) xx) && ((int) yy)) + if (((int)xx) && ((int)yy)) { double A = atan((yy / xx)); #if defined(DEBUG_GESTURE_LAYER) @@ -2329,27 +2357,27 @@ get_finger_gap_length(Evas_Coord x1, Evas_Coord y1, Evas_Coord x2, #endif a = (Evas_Coord) ((gap / 2) * sin(A)); b = (Evas_Coord) ((gap / 2) * cos(A)); - *x = (Evas_Coord) ((x2 > x1) ? (x1 + b) : (x2 + b)); - *y = (Evas_Coord) ((y2 > y1) ? (y1 + a) : (y2 + a)); + *x = (Evas_Coord) ((xx2 > xx1) ? (xx1 + b) : (xx2 + b)); + *y = (Evas_Coord) ((yy2 > yy1) ? (yy1 + a) : (yy2 + a)); } else { - if ((int) xx) + if ((int)xx) { /* horiz line, take half width */ #if defined(DEBUG_GESTURE_LAYER) printf("==== HORIZ ====\n"); #endif - *x = (Evas_Coord) (xx / 2); - *y = (Evas_Coord) (y1); + *x = (Evas_Coord) ((xx1 + xx2) / 2); + *y = (Evas_Coord) (yy1); } - if ((int) yy) + if ((int)yy) { /* vert line, take half width */ #if defined(DEBUG_GESTURE_LAYER) printf("==== VERT ====\n"); #endif - *x = (Evas_Coord) (x1); - *y = (Evas_Coord) (yy / 2); + *x = (Evas_Coord) (xx1); + *y = (Evas_Coord) ((yy1 + yy2) / 2); } } /* END - Compute zoom center point */ @@ -2374,6 +2402,15 @@ static double _zoom_momentum_get(Zoom_Type *st, unsigned int tm_end, double zoom_val) { unsigned int tm_total; + if (!st->m_st_tm) + { /* Init, and we don't start computing momentum yet */ + st->m_st_tm = st->m_prev_tm = tm_end; + st->m_base = zoom_val; + return 0.0; + } + + if ((tm_end - ELM_GESTURE_MOMENTUM_DELAY) < st->m_st_tm) + return 0.0; /* we don't start to compute momentum yet */ if (st->dir) { /* if direction was already defined, check if changed */ @@ -2382,21 +2419,23 @@ _zoom_momentum_get(Zoom_Type *st, unsigned int tm_end, double zoom_val) { /* Direction changed, reset momentum */ st->m_st_tm = 0; st->dir = (-st->dir); + return 0.0; } } else st->dir = (zoom_val > st->info.zoom) ? 1 : -1; /* init */ - if (!st->m_st_tm) + if ((tm_end - ELM_GESTURE_MOMENTUM_TIMEOUT) > st->m_prev_tm) { - st->m_st_tm = tm_end; - st->m_base = zoom_val; + st->m_st_tm = 0; /* Rest momentum when waiting too long */ + return 0.0; } + st->m_prev_tm = tm_end; tm_total = tm_end - st->m_st_tm; if (tm_total) - return (((zoom_val / st->m_base) - 1.0) * 1000) / tm_total; + return ((zoom_val - st->m_base) * 1000) / tm_total; else return 0.0; } @@ -2418,15 +2457,17 @@ _zoom_momentum_get(Zoom_Type *st, unsigned int tm_end, double zoom_val) * @ingroup Elm_Gesture_Layer */ static double -compute_zoom(Zoom_Type *st, Evas_Coord x1, Evas_Coord y1, - Evas_Coord x2, Evas_Coord y2, double zoom_finger_factor) +compute_zoom(Zoom_Type *st, + Evas_Coord xx1, Evas_Coord yy1, + Evas_Coord xx2, Evas_Coord yy2, + double zoom_finger_factor) { double rt = 1.0; unsigned int tm_end = (st->zoom_mv.timestamp > st->zoom_mv1.timestamp) ? - st->zoom_mv.timestamp : st->zoom_mv1.timestamp; + st->zoom_mv.timestamp : st->zoom_mv1.timestamp; - Evas_Coord diam = get_finger_gap_length(x1, y1, x2, y2, - &st->info.x, &st->info.y); + Evas_Coord diam = get_finger_gap_length(xx1, yy1, xx2, yy2, + &st->info.x, &st->info.y); st->info.radius = diam / 2; @@ -2456,7 +2497,7 @@ compute_zoom(Zoom_Type *st, Evas_Coord x1, Evas_Coord y1, /* We use factor only on the difference between gap-base */ /* if gap=120, base=100, we get ((120-100)/100)=0.2*factor */ rt = ((1.0) + ((((float) diam - (float) st->zoom_base) / - (float) st->zoom_base) * zoom_finger_factor)); + (float) st->zoom_base) * zoom_finger_factor)); /* Momentum: zoom per second: */ st->info.momentum = _zoom_momentum_get(st, tm_end, rt); @@ -2478,7 +2519,7 @@ compute_zoom(Zoom_Type *st, Evas_Coord x1, Evas_Coord y1, */ static void _zoom_with_wheel_test(Evas_Object *obj, void *event_info, - Evas_Callback_Type event_type, Elm_Gesture_Types g_type) + Evas_Callback_Type event_type, Elm_Gesture_Type g_type) { Widget_Data *wd = elm_widget_data_get(obj); if (!wd) return; @@ -2506,6 +2547,9 @@ _zoom_with_wheel_test(Evas_Object *obj, void *event_info, ((gesture_zoom->state == ELM_GESTURE_STATE_START) || (gesture_zoom->state == ELM_GESTURE_STATE_MOVE))) { /* User released CTRL after zooming */ + st->info.momentum = _zoom_momentum_get(st, + p->timestamp, st->info.zoom); + ev_flag = _set_state(gesture_zoom, ELM_GESTURE_STATE_END, &st->info, EINA_FALSE); consume_event(wd, event_info, event_type, ev_flag); @@ -2601,7 +2645,7 @@ _zoom_with_wheel_test(Evas_Object *obj, void *event_info, */ static void _zoom_test(Evas_Object *obj, Pointer_Event *pe, void *event_info, - Evas_Callback_Type event_type, Elm_Gesture_Types g_type) + Evas_Callback_Type event_type, Elm_Gesture_Type g_type) { if (!pe) return; @@ -2637,7 +2681,7 @@ _zoom_test(Evas_Object *obj, Pointer_Event *pe, void *event_info, Eina_List *l; Pointer_Event *p; - if(eina_list_count(wd->touched) > 2) + if (eina_list_count(wd->touched) > 2) { /* Process zoom only when 2 fingers on surface */ ev_flag = _set_state(gesture_zoom, ELM_GESTURE_STATE_ABORT, &st->info, EINA_FALSE); @@ -2697,10 +2741,10 @@ _zoom_test(Evas_Object *obj, Pointer_Event *pe, void *event_info, memcpy(&st->zoom_mv1, pe, sizeof(Pointer_Event)); /* Compute change in zoom as fingers move */ - st->info.zoom = compute_zoom(st, - st->zoom_mv.x, st->zoom_mv.y, - st->zoom_mv1.x, st->zoom_mv1.y, - wd->zoom_finger_factor); + st->info.zoom = compute_zoom(st, + st->zoom_mv.x, st->zoom_mv.y, + st->zoom_mv1.x, st->zoom_mv1.y, + wd->zoom_finger_factor); if (!st->zoom_distance_tolerance) { /* Zoom broke tolerance, report move */ @@ -2756,15 +2800,15 @@ _zoom_test(Evas_Object *obj, Pointer_Event *pe, void *event_info, static void _get_rotate_properties(Rotate_Type *st, - Evas_Coord x1, Evas_Coord y1, - Evas_Coord x2, Evas_Coord y2, - double *angle) -{ + Evas_Coord xx1, Evas_Coord yy1, + Evas_Coord xx2, Evas_Coord yy2, + double *angle) +{ /* FIXME: Fix momentum computation, it's wrong */ double prev_angle = *angle; - st->info.radius = get_finger_gap_length(x1, y1, x2, y2, - &st->info.x, &st->info.y) / 2; + st->info.radius = get_finger_gap_length(xx1, yy1, xx2, yy2, + &st->info.x, &st->info.y) / 2; - *angle = get_angle(x1, y1, x2, y2); + *angle = get_angle(xx1, yy1, xx2, yy2); if (angle == &st->info.angle) { /* Fingers are moving, compute momentum */ @@ -2778,13 +2822,14 @@ _get_rotate_properties(Rotate_Type *st, unsigned int tm_total = tm_end - tm_start; if (tm_total) { /* Momentum computed as: - accumulated roation angle (rad) divided by time */ - double m; - if ((prev_angle >= RAD_270DEG) && ((*angle) < RAD_180DEG)) + accumulated roation angle (deg) divided by time */ + double m = 0;; + if (((prev_angle < 90) && ((*angle) > 270)) || + ((prev_angle > 270) && ((*angle) < 90))) { /* We circle passing ZERO point */ - m = (RAD_360DEG - prev_angle) + (*angle); + prev_angle = (*angle); } - else m = (*angle) - prev_angle; + else m = prev_angle - (*angle); st->accum_momentum += m; @@ -2796,9 +2841,9 @@ _get_rotate_properties(Rotate_Type *st, st->accum_momentum = 0.0; /* reset momentum */ st->prev_momentum = 0.0; /* Start again */ - st->prev_momentum_tm = tm_end; } + st->prev_momentum_tm = tm_end; st->info.momentum = (st->accum_momentum * 1000) / tm_total; } } @@ -2823,7 +2868,7 @@ _get_rotate_properties(Rotate_Type *st, */ static void _rotate_test(Evas_Object *obj, Pointer_Event *pe, void *event_info, - Evas_Callback_Type event_type, Elm_Gesture_Types g_type) + Evas_Callback_Type event_type, Elm_Gesture_Type g_type) { if (!pe) return; @@ -2861,7 +2906,7 @@ _rotate_test(Evas_Object *obj, Pointer_Event *pe, void *event_info, Eina_List *l; Pointer_Event *p; - if(eina_list_count(wd->touched) > 2) + if (eina_list_count(wd->touched) > 2) { /* Process rotate only when 2 fingers on surface */ ev_flag = _set_state(gesture, ELM_GESTURE_STATE_ABORT, &st->info, EINA_FALSE); @@ -2923,7 +2968,7 @@ _rotate_test(Evas_Object *obj, Pointer_Event *pe, void *event_info, if (rotation_broke_tolerance(st)) { /* Rotation broke tolerance, report move */ double d = st->info.angle - st->next_step; - if (d < 0.0) + if (d < 0) d = (-d); if (d >= wd->rotate_step) @@ -3059,7 +3104,8 @@ _make_pointer_event(void *data, void *event_info, * * @ingroup Elm_Gesture_Layer */ -void continues_gestures_restart(void *data, Eina_Bool states_reset) +static void +continues_gestures_restart(void *data, Eina_Bool states_reset) { Widget_Data *wd = elm_widget_data_get(data); if (!wd) return; @@ -3149,16 +3195,15 @@ _event_process(void *data, Evas_Object *obj __UNUSED__, Pointer_Event _pe; Pointer_Event *pe = NULL; Widget_Data *wd = elm_widget_data_get(data); - if (!wd) return; #if defined(DEBUG_GESTURE_LAYER) int i; Gesture_Info *g; printf("Gesture | State | is tested\n"); - for(i = ELM_GESTURE_N_TAPS; i < ELM_GESTURE_LAST; i++) + for (i = ELM_GESTURE_N_TAPS; i < ELM_GESTURE_LAST; i++) { g = wd->gesture[i]; - if(g) + if (g) printf(" %d %d %d\n", i, g->state, g->test); } #endif @@ -3171,8 +3216,17 @@ _event_process(void *data, Evas_Object *obj __UNUSED__, _n_long_tap_test(data, pe, event_info, event_type, ELM_GESTURE_N_LONG_TAPS); - /* This takes care of single, double and tripple tap */ - _tap_gestures_test(data, pe, event_info, event_type); + if (IS_TESTED(ELM_GESTURE_N_TAPS)) + _tap_gesture_test(wd, pe, event_info, event_type, + wd->gesture[ELM_GESTURE_N_TAPS], 1); + + if (IS_TESTED(ELM_GESTURE_N_DOUBLE_TAPS)) + _tap_gesture_test(wd, pe, event_info, event_type, + wd->gesture[ELM_GESTURE_N_DOUBLE_TAPS], 2); + + if (IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS)) + _tap_gesture_test(wd, pe, event_info, event_type, + wd->gesture[ELM_GESTURE_N_TRIPLE_TAPS], 3); if (IS_TESTED(ELM_GESTURE_MOMENTUM)) _momentum_test(data, pe, event_info, event_type, @@ -3195,16 +3249,6 @@ _event_process(void *data, Evas_Object *obj __UNUSED__, if (_get_event_flag(event_info, event_type) & EVAS_EVENT_FLAG_ON_HOLD) _event_history_add(data, event_info, event_type); - else if ((event_type == EVAS_CALLBACK_MOUSE_UP) || - (event_type == EVAS_CALLBACK_MULTI_UP)) - { - Eina_List *pending = _device_is_pending(wd->pending, event_info, event_type); - if (pending) - { - consume_event(wd, event_info, event_type, EVAS_EVENT_FLAG_ON_HOLD); - _event_history_add(data, event_info, event_type); - } - } /* we maintain list of touched devices */ /* We also use move to track current device x.y pos */ @@ -3333,8 +3377,10 @@ _multi_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, } EAPI Eina_Bool -elm_gesture_layer_hold_events_get(Evas_Object *obj) +elm_gesture_layer_hold_events_get(const Evas_Object *obj) { + ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; + Widget_Data *wd = elm_widget_data_get(obj); if (!wd) return EINA_FALSE; @@ -3342,61 +3388,90 @@ elm_gesture_layer_hold_events_get(Evas_Object *obj) } EAPI void -elm_gesture_layer_hold_events_set(Evas_Object *obj, Eina_Bool r) +elm_gesture_layer_hold_events_set(Evas_Object *obj, Eina_Bool hold_events) { + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); if (!wd) return; - wd->repeat_events = !r; + wd->repeat_events = !(!!hold_events); +} + +EAPI double +elm_gesture_layer_zoom_step_get(const Evas_Object *obj) +{ + ELM_CHECK_WIDTYPE(obj, widtype) 0; + + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return 0; + + return wd->zoom_step; } EAPI void -elm_gesture_layer_zoom_step_set(Evas_Object *obj, double s) +elm_gesture_layer_zoom_step_set(Evas_Object *obj, double step) { + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); if (!wd) return; - if (s < 0.0) - return; + if (step < 0) return; - wd->zoom_step = s; + wd->zoom_step = step; +} + +EAPI double +elm_gesture_layer_rotate_step_get(const Evas_Object *obj) +{ + ELM_CHECK_WIDTYPE(obj, widtype) 0; + + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return 0; + + return wd->rotate_step; } EAPI void -elm_gesture_layer_rotate_step_set(Evas_Object *obj, double s) +elm_gesture_layer_rotate_step_set(Evas_Object *obj, double step) { + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); if (!wd) return; - if (s < 0.0) - return; + if (step < 0) return; - wd->rotate_step = s; + wd->rotate_step = step; } EAPI Eina_Bool -elm_gesture_layer_attach(Evas_Object *obj, Evas_Object *t) +elm_gesture_layer_attach(Evas_Object *obj, Evas_Object *target) { + ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; + Widget_Data *wd = elm_widget_data_get(obj); if (!wd) return EINA_FALSE; - if (!t) - return EINA_FALSE; + if (!target) return EINA_FALSE; /* if was attached before, unregister callbacks first */ if (wd->target) _unregister_callbacks(obj); - wd->target = t; + wd->target = target; _register_callbacks(obj); return EINA_TRUE; } EAPI void -elm_gesture_layer_cb_set(Evas_Object *obj, Elm_Gesture_Types idx, +elm_gesture_layer_cb_set(Evas_Object *obj, Elm_Gesture_Type idx, Elm_Gesture_State cb_type, Elm_Gesture_Event_Cb cb, void *data) { + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); Gesture_Info *p; if (!wd) return; @@ -3440,9 +3515,9 @@ elm_gesture_layer_add(Evas_Object *parent) elm_widget_disable_hook_set(obj, _disable_hook); wd->target = NULL; - wd->line_min_length =_elm_config->glayer_line_min_length * elm_finger_size_get(); - wd->zoom_distance_tolerance = _elm_config->glayer_zoom_distance_tolerance * elm_finger_size_get(); - wd->line_distance_tolerance = _elm_config->glayer_line_distance_tolerance * elm_finger_size_get(); + wd->line_min_length =_elm_config->glayer_line_min_length * _elm_config->finger_size; + wd->zoom_distance_tolerance = _elm_config->glayer_zoom_distance_tolerance * _elm_config->finger_size; + wd->line_distance_tolerance = _elm_config->glayer_line_distance_tolerance * _elm_config->finger_size; wd->zoom_finger_factor = _elm_config->glayer_zoom_finger_factor; wd->zoom_wheel_factor = _elm_config->glayer_zoom_wheel_factor; /* mouse wheel zoom steps */ wd->rotate_angular_tolerance = _elm_config->glayer_rotate_angular_tolerance;