forked from enlightenment/efl
Gesture Layer: fix to improve fingers taps registration
Signed-off-by: Aharon Hillel <a.hillel@samsung.com>
This commit is contained in:
parent
1b1e1f99e3
commit
dcab3545cf
|
@ -1553,11 +1553,6 @@ _pe_device_compare(const void *data1,
|
||||||
const Pointer_Event *pe1 = eina_list_data_get(data1);
|
const Pointer_Event *pe1 = eina_list_data_get(data1);
|
||||||
const Pointer_Event *pe2 = data2;
|
const Pointer_Event *pe2 = data2;
|
||||||
|
|
||||||
/* Only match if last was a down event */
|
|
||||||
if ((pe1->event_type != EVAS_CALLBACK_MULTI_DOWN) &&
|
|
||||||
(pe1->event_type != EVAS_CALLBACK_MOUSE_DOWN))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (pe1->device == pe2->device)
|
if (pe1->device == pe2->device)
|
||||||
return 0;
|
return 0;
|
||||||
else if (pe1->device < pe2->device)
|
else if (pe1->device < pe2->device)
|
||||||
|
@ -1600,6 +1595,51 @@ _pointer_event_record(Taps_Type *st,
|
||||||
return pe_list;
|
return pe_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* This function computes minimum rect to bound taps at idx index
|
||||||
|
*
|
||||||
|
* @param taps [in] List of lists containing taps info.
|
||||||
|
* @param idx [in] index of events taken from lists.
|
||||||
|
* @param r [out] rect object to save info
|
||||||
|
* @return EINA_TRUE if managed to compute rect.
|
||||||
|
*
|
||||||
|
* @ingroup Elm_Gesture_Layer
|
||||||
|
*/
|
||||||
|
static Eina_Bool
|
||||||
|
_taps_rect_get(Eina_List *taps, int idx, Evas_Coord_Rectangle *r)
|
||||||
|
{ /* Build a rect bounding all taps at index idx */
|
||||||
|
Eina_List *l;
|
||||||
|
Evas_Coord bx, by;
|
||||||
|
Eina_List *pe_list;
|
||||||
|
Eina_Bool was_init = EINA_FALSE;
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(taps, l, pe_list)
|
||||||
|
{
|
||||||
|
Pointer_Event *pe = eina_list_nth(pe_list, idx);
|
||||||
|
if (!pe) continue; /* Not suppose to happen */
|
||||||
|
|
||||||
|
if (was_init)
|
||||||
|
{
|
||||||
|
if (pe->x < r->x) r->x = pe->x;
|
||||||
|
if (pe->y < r->y) r->y = pe->y;
|
||||||
|
if (pe->x > bx) bx = pe->x;
|
||||||
|
if (pe->y > by) by = pe->y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r->x = bx = pe->x;
|
||||||
|
r->y = by = pe->y;
|
||||||
|
was_init = EINA_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r->w = bx - r->x;
|
||||||
|
r->h = by - r->y;
|
||||||
|
return was_init;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*
|
*
|
||||||
|
@ -1616,9 +1656,13 @@ _tap_gesture_check_finish(Gesture_Info *gesture)
|
||||||
/* Here we check if taps-gesture was completed successfuly */
|
/* Here we check if taps-gesture was completed successfuly */
|
||||||
/* Count how many taps were recieved on each device then */
|
/* Count how many taps were recieved on each device then */
|
||||||
/* determine if it matches n_taps_needed defined on START */
|
/* determine if it matches n_taps_needed defined on START */
|
||||||
|
unsigned int i;
|
||||||
Taps_Type *st = gesture->data;
|
Taps_Type *st = gesture->data;
|
||||||
Eina_List *l;
|
Eina_List *l;
|
||||||
Eina_List *pe_list;
|
Eina_List *pe_list;
|
||||||
|
Evas_Coord_Rectangle base;
|
||||||
|
Evas_Coord_Rectangle tmp;
|
||||||
|
Evas_Coord tap_finger_size = elm_config_finger_size_get();
|
||||||
|
|
||||||
if (!st->l) return EINA_FALSE;
|
if (!st->l) return EINA_FALSE;
|
||||||
EINA_LIST_FOREACH(st->l, l, pe_list)
|
EINA_LIST_FOREACH(st->l, l, pe_list)
|
||||||
|
@ -1630,6 +1674,29 @@ _tap_gesture_check_finish(Gesture_Info *gesture)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Now bound each tap touches in a rect, compare diff within tolerance */
|
||||||
|
/* Get rect based on first DOWN events for all devices */
|
||||||
|
if (!_taps_rect_get(st->l, 0, &base))
|
||||||
|
return EINA_FALSE; /* Should not happen */
|
||||||
|
|
||||||
|
for(i = 1; i < st->n_taps_needed; i++)
|
||||||
|
{ /* Compare all other rects to base, tolerance is finger size */
|
||||||
|
if (_taps_rect_get(st->l, i, &tmp))
|
||||||
|
{
|
||||||
|
if (abs(tmp.x - base.x) > tap_finger_size)
|
||||||
|
return EINA_FALSE;
|
||||||
|
|
||||||
|
if (abs(tmp.y - base.y) > tap_finger_size)
|
||||||
|
return EINA_FALSE;
|
||||||
|
|
||||||
|
if (abs((tmp.x + tmp.w) - (base.x + base.w)) > tap_finger_size)
|
||||||
|
return EINA_FALSE;
|
||||||
|
|
||||||
|
if (abs((tmp.y + tmp.h) - (base.y + base.h)) > tap_finger_size)
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1736,7 +1803,7 @@ _tap_gesture_test(Evas_Object *obj,
|
||||||
Taps_Type *st;
|
Taps_Type *st;
|
||||||
Gesture_Info *gesture;
|
Gesture_Info *gesture;
|
||||||
Eina_List *pe_list = NULL;
|
Eina_List *pe_list = NULL;
|
||||||
Pointer_Event *pe_down = NULL;
|
Pointer_Event *pe_last = NULL;
|
||||||
Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
|
Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
|
||||||
|
|
||||||
/* Here we fill Tap struct */
|
/* Here we fill Tap struct */
|
||||||
|
@ -1751,20 +1818,20 @@ _tap_gesture_test(Evas_Object *obj,
|
||||||
switch (g_type)
|
switch (g_type)
|
||||||
{
|
{
|
||||||
case ELM_GESTURE_N_TAPS:
|
case ELM_GESTURE_N_TAPS:
|
||||||
taps = 1;
|
taps = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ELM_GESTURE_N_DOUBLE_TAPS:
|
case ELM_GESTURE_N_DOUBLE_TAPS:
|
||||||
taps = 2;
|
taps = 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ELM_GESTURE_N_TRIPLE_TAPS:
|
case ELM_GESTURE_N_TRIPLE_TAPS:
|
||||||
taps = 3;
|
taps = 3;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
taps = 0;
|
taps = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
st = gesture->data;
|
st = gesture->data;
|
||||||
|
@ -1779,94 +1846,105 @@ _tap_gesture_test(Evas_Object *obj,
|
||||||
{
|
{
|
||||||
case EVAS_CALLBACK_MULTI_DOWN:
|
case EVAS_CALLBACK_MULTI_DOWN:
|
||||||
case EVAS_CALLBACK_MOUSE_DOWN:
|
case EVAS_CALLBACK_MOUSE_DOWN:
|
||||||
/* Check if got tap on same cord was tapped before */
|
/* Each device taps (DOWN, UP event) registered in same list */
|
||||||
pe_list = eina_list_search_unsorted(st->l, _match_fingers_compare, pe);
|
/* Find list for this device or start a new list if not found */
|
||||||
|
pe_list = eina_list_search_unsorted(st->l, _pe_device_compare, pe);
|
||||||
|
if (pe_list)
|
||||||
|
{ /* This device touched before, verify that this tap is on */
|
||||||
|
/* top of a previous tap (including a tap of other device) */
|
||||||
|
if (!eina_list_search_unsorted(st->l, _match_fingers_compare, pe))
|
||||||
|
{ /* New DOWN event is not on top of any prev touch */
|
||||||
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
|
||||||
|
&st->info, EINA_FALSE);
|
||||||
|
_event_consume(sd, event_info, event_type, ev_flag);
|
||||||
|
|
||||||
if ((!pe_list) &&
|
return;
|
||||||
/* This device was touched in other cord before completion */
|
}
|
||||||
eina_list_search_unsorted(st->l, _pe_device_compare, pe))
|
}
|
||||||
{
|
|
||||||
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
|
|
||||||
&st->info, EINA_FALSE);
|
|
||||||
_event_consume(sd, event_info, event_type, ev_flag);
|
|
||||||
|
|
||||||
return;
|
/* All tests are good, register this tap in device list */
|
||||||
}
|
pe_list = _pointer_event_record
|
||||||
|
|
||||||
pe_list = _pointer_event_record
|
|
||||||
(st, pe_list, pe, sd, event_info, event_type);
|
(st, pe_list, pe, sd, event_info, event_type);
|
||||||
if (!sd->gest_taps_timeout)
|
|
||||||
{
|
|
||||||
if (sd->double_tap_timeout > 0.0)
|
|
||||||
{
|
|
||||||
sd->gest_taps_timeout =
|
|
||||||
ecore_timer_add(sd->double_tap_timeout,
|
|
||||||
_multi_tap_timeout, gesture->obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ecore_timer_reset(sd->gest_taps_timeout);
|
|
||||||
|
|
||||||
/* This is the first mouse down we got */
|
if (!sd->gest_taps_timeout)
|
||||||
if ((pe->device == 0) && (eina_list_count(pe_list) == 1))
|
{
|
||||||
{
|
if (sd->double_tap_timeout > 0.0)
|
||||||
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_START,
|
{
|
||||||
&st->info, EINA_FALSE);
|
sd->gest_taps_timeout =
|
||||||
_event_consume(sd, event_info, event_type, ev_flag);
|
ecore_timer_add(sd->double_tap_timeout,
|
||||||
|
_multi_tap_timeout, gesture->obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* We re-allocate gest_taps_timeout between taps */
|
||||||
|
ecore_timer_reset(sd->gest_taps_timeout);
|
||||||
|
|
||||||
st->n_taps_needed = taps * 2; /* count DOWN and UP */
|
if ((pe->device == 0) && (eina_list_count(pe_list) == 1))
|
||||||
|
{ /* This is the first mouse down we got */
|
||||||
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_START,
|
||||||
|
&st->info, EINA_FALSE);
|
||||||
|
_event_consume(sd, event_info, event_type, ev_flag);
|
||||||
|
|
||||||
return;
|
st->n_taps_needed = taps * 2; /* count DOWN and UP */
|
||||||
}
|
|
||||||
else if (eina_list_count(pe_list) > st->n_taps_needed)
|
|
||||||
/* If we arleady got too many touches for this gesture. */
|
|
||||||
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
|
|
||||||
&st->info, EINA_FALSE);
|
|
||||||
|
|
||||||
break;
|
return;
|
||||||
|
}
|
||||||
|
else if (eina_list_count(pe_list) > st->n_taps_needed)
|
||||||
|
{ /* If we arleady got too many touches for this gesture. */
|
||||||
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
|
||||||
|
&st->info, EINA_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case EVAS_CALLBACK_MULTI_UP:
|
case EVAS_CALLBACK_MULTI_UP:
|
||||||
case EVAS_CALLBACK_MOUSE_UP:
|
case EVAS_CALLBACK_MOUSE_UP:
|
||||||
pe_list = eina_list_search_unsorted(st->l, _pe_device_compare, pe);
|
pe_list = eina_list_search_unsorted(st->l, _pe_device_compare, pe);
|
||||||
if (!pe_list) return;
|
if (!pe_list) return;
|
||||||
|
|
||||||
pe_list = _pointer_event_record
|
pe_list = _pointer_event_record
|
||||||
(st, pe_list, pe, sd, event_info, event_type);
|
(st, pe_list, pe, sd, event_info, event_type);
|
||||||
|
|
||||||
if (((gesture->g_type == ELM_GESTURE_N_TAPS) &&
|
if (((gesture->g_type == ELM_GESTURE_N_TAPS) &&
|
||||||
!IS_TESTED(ELM_GESTURE_N_DOUBLE_TAPS) &&
|
!IS_TESTED(ELM_GESTURE_N_DOUBLE_TAPS) &&
|
||||||
!IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS)) ||
|
!IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS)) ||
|
||||||
((gesture->g_type == ELM_GESTURE_N_DOUBLE_TAPS) &&
|
((gesture->g_type == ELM_GESTURE_N_DOUBLE_TAPS) &&
|
||||||
!IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS)))
|
!IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS)))
|
||||||
{
|
{ /* Test for finish immidiatly, not waiting for timeout */
|
||||||
if (_tap_gesture_check_finish(gesture))
|
if (_tap_gesture_check_finish(gesture))
|
||||||
{
|
{
|
||||||
_tap_gesture_finish(gesture);
|
_tap_gesture_finish(gesture);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EVAS_CALLBACK_MULTI_MOVE:
|
case EVAS_CALLBACK_MULTI_MOVE:
|
||||||
case EVAS_CALLBACK_MOUSE_MOVE:
|
case EVAS_CALLBACK_MOUSE_MOVE:
|
||||||
/* Get first event in first list, this has to be a Mouse Down event */
|
/* Verify that user didn't move out of tap area before next tap */
|
||||||
/* and verify that user didn't move out of this area before next tap */
|
/* BUT: we need to skip some MOVE events coming before DOWN */
|
||||||
pe_list = eina_list_search_unsorted(st->l, _pe_device_compare, pe);
|
/* when user taps next tap. So fetch LAST recorded event for */
|
||||||
if (pe_list)
|
/* device (DOWN or UP event), ignore all MOVEs if last was UP */
|
||||||
{
|
pe_last = eina_list_data_get(eina_list_last(
|
||||||
pe_down = eina_list_data_get(pe_list);
|
eina_list_search_unsorted(st->l, _pe_device_compare, pe)));
|
||||||
if (!_inside(pe_down->x, pe_down->y, pe->x, pe->y))
|
|
||||||
{
|
if (pe_last)
|
||||||
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
|
{ /* pe_last is the last event recorded for this device */
|
||||||
&st->info, EINA_FALSE);
|
if ((pe_last->event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
|
||||||
_event_consume(sd, event_info, event_type, ev_flag);
|
(pe_last->event_type == EVAS_CALLBACK_MULTI_DOWN))
|
||||||
}
|
{ /* Test only MOVE events that come after DOWN event */
|
||||||
}
|
if (!_inside(pe_last->x, pe_last->y, pe->x, pe->y))
|
||||||
break;
|
{
|
||||||
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
|
||||||
|
&st->info, EINA_FALSE);
|
||||||
|
_event_consume(sd, event_info, event_type, ev_flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue