+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
#include <Elementary.h>
#include "elm_priv.h"
-EAPI Eo_Op ELM_OBJ_GESTURE_LAYER_BASE_ID = EO_NOOP;
-
-#define MY_CLASS ELM_OBJ_GESTURE_LAYER_CLASS
+#define MY_CLASS ELM_GESTURE_LAYER_CLASS
-#define MY_CLASS_NAME "elm_gesture_layer"
+#define MY_CLASS_NAME "Elm_Gesture_Layer"
+#define MY_CLASS_NAME_LEGACY "elm_gesture_layer"
/* Some defaults */
#define ELM_MOUSE_DEVICE 0
#define SET_TEST_BIT(P) \
do { \
- P->test = P->fn[ELM_GESTURE_STATE_START].cb || \
- P->fn[ELM_GESTURE_STATE_MOVE].cb || \
- P->fn[ELM_GESTURE_STATE_END].cb || \
- P->fn[ELM_GESTURE_STATE_ABORT].cb; \
+ P->test = P->cbs[ELM_GESTURE_STATE_START] || \
+ P->cbs[ELM_GESTURE_STATE_MOVE] || \
+ P->cbs[ELM_GESTURE_STATE_END] || \
+ P->cbs[ELM_GESTURE_STATE_ABORT]; \
} while (0)
#define IS_TESTED_GESTURE(gesture) \
((sd->gesture[T]) ? sd->gesture[T]->test : EINA_FALSE)
#define ELM_GESTURE_LAYER_DATA_GET(o, sd) \
- Elm_Gesture_Layer_Smart_Data * sd = eo_data_get(o, MY_CLASS)
+ Elm_Gesture_Layer_Data * sd = eo_data_scope_get(o, MY_CLASS)
#define ELM_GESTURE_LAYER_DATA_GET_OR_RETURN(o, ptr) \
ELM_GESTURE_LAYER_DATA_GET(o, ptr); \
if (!ptr) \
{ \
- CRITICAL("No widget data for object %p (%s)", \
+ CRI("No widget data for object %p (%s)", \
o, evas_object_type_get(o)); \
return; \
}
ELM_GESTURE_LAYER_DATA_GET(o, ptr); \
if (!ptr) \
{ \
- CRITICAL("No widget data for object %p (%s)", \
+ CRI("No widget data for object %p (%s)", \
o, evas_object_type_get(o)); \
return val; \
}
*/
struct _Func_Data
{
+ EINA_INLIST;
void *user_data; /**< Holds user data to CB (like sd) */
Elm_Gesture_Event_Cb cb;
};
{
Evas_Object *obj;
void *data; /**< Holds gesture intemidiate processing data */
- Func_Data fn[ELM_GESTURE_STATE_ABORT + 1]; /**< Callback info for states */
+ Eina_Inlist *cbs[ELM_GESTURE_STATE_ABORT + 1]; /**< Callback info (Func_Data) for states */
Elm_Gesture_Type g_type; /**< gesture type */
Elm_Gesture_State state; /**< gesture state */
void *info; /**< Data for the state callback */
void *event_info,
Evas_Callback_Type event_type);
+static void _callbacks_unregister(Evas_Object *obj);
+
/* Should be the same order as _Elm_Gesture_Type */
static Tests_Array_Funcs _glayer_tests_array[] = {
{ NULL, NULL, NULL }, /** Because someone made an awful mistake. */
};
typedef struct _Rotate_Type Rotate_Type;
-typedef struct _Elm_Gesture_Layer_Smart_Data Elm_Gesture_Layer_Smart_Data;
-struct _Elm_Gesture_Layer_Smart_Data
+typedef struct _Elm_Gesture_Layer_Data Elm_Gesture_Layer_Data;
+struct _Elm_Gesture_Layer_Data
{
Evas_Object *target; /* Target Widget */
Event_History *event_history_list;
Eina_List *touched; /* Information of touched devices */
/* Taps Gestures */
+ Evas_Coord tap_finger_size; /* Default from Config */
Ecore_Timer *gest_taps_timeout; /* When this expires, dbl
* click/taps ABORTed */
* @ingroup Elm_Gesture_Layer
*/
static void
-_event_consume(Elm_Gesture_Layer_Smart_Data *sd,
+_event_consume(Elm_Gesture_Layer_Data *sd,
void *event_info,
Evas_Callback_Type event_type,
Evas_Event_Flags ev_flags)
_state_report(Gesture_Info *gesture,
void *info)
{
+ Evas_Event_Flags flags = EVAS_EVENT_FLAG_NONE;
/* We report current state (START, MOVE, END, ABORT), once */
if ((gesture->state != ELM_GESTURE_STATE_UNDEFINED) &&
- (gesture->fn[gesture->state].cb)) /* Fill state-info struct and
- * send ptr to user
- * callback */
+ (gesture->cbs[gesture->state])) /* Fill state-info struct and
+ * send ptr to user
+ * callback */
{
- return gesture->fn[gesture->state].cb(
- gesture->fn[gesture->state].user_data, info);
+ Func_Data *cb_info;
+ EINA_INLIST_FOREACH(gesture->cbs[gesture->state], cb_info)
+ flags |= cb_info->cb(cb_info->user_data, info);
}
return EVAS_EVENT_FLAG_NONE;
* @ingroup Elm_Gesture_Layer
*/
static void
-_states_reset(Elm_Gesture_Layer_Smart_Data *sd)
+_states_reset(Elm_Gesture_Layer_Data *sd)
{
int i;
Gesture_Info *p;
* @ingroup Elm_Gesture_Layer
*/
static Eina_Bool
-_pointer_event_make(void *data __UNUSED__,
+_pointer_event_make(void *data EINA_UNUSED,
void *event_info,
Evas_Callback_Type event_type,
Pointer_Event *pe)
ELM_GESTURE_LAYER_DATA_GET(obj, sd);
ev = malloc(sizeof(Event_History));
+ if (!ev) return EINA_FALSE;
+
ev->event = _event_info_copy(event, event_type); /* Freed on
* _event_history_clear */
ev->event_type = event_type;
*/
static void
_mouse_down_cb(void *data,
- Evas *e __UNUSED__,
- Evas_Object *obj __UNUSED__,
+ Evas *e EINA_UNUSED,
+ Evas_Object *obj EINA_UNUSED,
void *event_info)
{
if (((Evas_Event_Mouse_Down *)event_info)->button != 1)
static void
_mouse_move_cb(void *data,
- Evas *e __UNUSED__,
- Evas_Object *obj __UNUSED__,
+ Evas *e EINA_UNUSED,
+ Evas_Object *obj EINA_UNUSED,
void *event_info)
{
_event_process(data, obj, event_info, EVAS_CALLBACK_MOUSE_MOVE);
static void
_key_down_cb(void *data,
- Evas *e __UNUSED__,
- Evas_Object *obj __UNUSED__,
+ Evas *e EINA_UNUSED,
+ Evas_Object *obj EINA_UNUSED,
void *event_info)
{
_event_process(data, obj, event_info, EVAS_CALLBACK_KEY_DOWN);
static void
_key_up_cb(void *data,
- Evas *e __UNUSED__,
- Evas_Object *obj __UNUSED__,
+ Evas *e EINA_UNUSED,
+ Evas_Object *obj EINA_UNUSED,
void *event_info)
{
_event_process(data, obj, event_info, EVAS_CALLBACK_KEY_UP);
static void
_mouse_up_cb(void *data,
- Evas *e __UNUSED__,
- Evas_Object *obj __UNUSED__,
+ Evas *e EINA_UNUSED,
+ Evas_Object *obj EINA_UNUSED,
void *event_info)
{
if (((Evas_Event_Mouse_Up *)event_info)->button != 1)
static void
_mouse_wheel_cb(void *data,
- Evas *e __UNUSED__,
- Evas_Object *obj __UNUSED__,
+ Evas *e EINA_UNUSED,
+ Evas_Object *obj EINA_UNUSED,
void *event_info)
{
_event_process(data, obj, event_info, EVAS_CALLBACK_MOUSE_WHEEL);
static void
_multi_down_cb(void *data,
- Evas *e __UNUSED__,
- Evas_Object *obj __UNUSED__,
+ Evas *e EINA_UNUSED,
+ Evas_Object *obj EINA_UNUSED,
void *event_info)
{
/* Skip the mouse duplicates. */
static void
_multi_move_cb(void *data,
- Evas *e __UNUSED__,
- Evas_Object *obj __UNUSED__,
+ Evas *e EINA_UNUSED,
+ Evas_Object *obj EINA_UNUSED,
void *event_info)
{
/* Skip the mouse duplicates. */
static void
_multi_up_cb(void *data,
- Evas *e __UNUSED__,
- Evas_Object *obj __UNUSED__,
+ Evas *e EINA_UNUSED,
+ Evas_Object *obj EINA_UNUSED,
void *event_info)
{
/* Skip the mouse duplicates. */
_event_process(data, obj, event_info, EVAS_CALLBACK_MULTI_UP);
}
+static void
+_target_del_cb(void *data,
+ Evas *e EINA_UNUSED,
+ Evas_Object *obj EINA_UNUSED,
+ void *event_info EINA_UNUSED)
+{
+ _callbacks_unregister(data);
+ ELM_GESTURE_LAYER_DATA_GET(data, sd);
+ sd->target = NULL;
+}
+
/**
* @internal
*
(sd->target, EVAS_CALLBACK_KEY_DOWN, _key_down_cb, obj);
evas_object_event_callback_add
(sd->target, EVAS_CALLBACK_KEY_UP, _key_up_cb, obj);
+
+ evas_object_event_callback_add
+ (sd->target, EVAS_CALLBACK_DEL, _target_del_cb, obj);
}
/**
(sd->target, EVAS_CALLBACK_KEY_DOWN, _key_down_cb, obj);
evas_object_event_callback_del_full
(sd->target, EVAS_CALLBACK_KEY_UP, _key_up_cb, obj);
+
+ evas_object_event_callback_del_full
+ (sd->target, EVAS_CALLBACK_DEL, _target_del_cb, obj);
}
/**
}
else
{ /* Report ABORT to all gestures that still not finished */
- _state_set(p, ELM_GESTURE_STATE_ABORT, sd->gesture[i]->info,
- EINA_FALSE);
+ if (sd->target)
+ _state_set(p, ELM_GESTURE_STATE_ABORT,
+ sd->gesture[i]->info, EINA_FALSE);
}
}
}
*/
static void
_event_process(void *data,
- Evas_Object *obj __UNUSED__,
+ Evas_Object *obj EINA_UNUSED,
void *event_info,
Evas_Callback_Type event_type)
{
_inside(Evas_Coord xx1,
Evas_Coord yy1,
Evas_Coord xx2,
- Evas_Coord yy2)
+ Evas_Coord yy2,
+ Evas_Coord w)
{
- int w = elm_config_finger_size_get() >> 1; /* Finger size devided by 2 */
+ w >>= 1; /* Use half the distance, from center to all directions */
+ if (!w) /* use system default instead */
+ w = elm_config_finger_size_get() >> 1; /* Finger size divided by 2 */
if (xx1 < (xx2 - w))
return EINA_FALSE;
EINA_SAFETY_ON_NULL_RETURN(gesture);
ELM_GESTURE_LAYER_DATA_GET(gesture->obj, sd);
- if (sd->gest_taps_timeout)
- {
- ecore_timer_del(sd->gest_taps_timeout);
- sd->gest_taps_timeout = NULL;
- }
+ ELM_SAFE_FREE(sd->gest_taps_timeout, ecore_timer_del);
if (!gesture->data)
return;
static void
_n_long_tap_test_reset(Gesture_Info *gesture)
{
- Eina_List *l;
Pointer_Event *p;
Long_Tap_Type *st;
st = gesture->data;
- EINA_LIST_FOREACH(st->touched, l, p)
+ EINA_LIST_FREE(st->touched, p)
free(p);
+ st->touched = NULL;
- eina_list_free(st->touched);
- if (st->timeout)
- {
- ecore_timer_del(st->timeout);
- st->timeout = NULL;
- }
+ ELM_SAFE_FREE(st->timeout, ecore_timer_del);
memset(gesture->data, 0, sizeof(Long_Tap_Type));
}
static void
_line_test_reset(Gesture_Info *gesture)
{
- Eina_List *l;
Line_Type *st;
- Eina_List *list;
Line_Data *t_line;
EINA_SAFETY_ON_NULL_RETURN(gesture);
if (!gesture->data) return;
st = gesture->data;
- list = st->list;
- EINA_LIST_FOREACH(list, l, t_line)
+ EINA_LIST_FREE(st->list, t_line)
free(t_line);
-
- eina_list_free(list);
st->list = NULL;
}
st->rotate_angular_tolerance = sd->rotate_angular_tolerance;
}
-static int
-_match_fingers_compare(const void *data1,
- const void *data2)
+static Eina_List *
+_match_fingers_compare(Eina_List *list,
+ Pointer_Event *pe1,
+ Evas_Coord w)
{
- /* Compare coords of first item in list to cur coords */
- const Pointer_Event *pe1 = eina_list_data_get(data1);
- const Pointer_Event *pe2 = data2;
+ /* Compare coords of first item in list to cur coords */
+ Eina_List *pe_list;
+ Eina_List *l;
- if (_inside(pe1->x, pe1->y, pe2->x, pe2->y))
- return 0;
- else if (pe1->x < pe2->x)
- return -1;
- else
+ EINA_LIST_FOREACH(list, l, pe_list)
{
- if (pe1->x == pe2->x)
- return pe1->y - pe2->y;
- else
- return 1;
+ Pointer_Event *pe2 = eina_list_data_get(pe_list);
+
+ if (_inside(pe1->x, pe1->y, pe2->x, pe2->y, w))
+ return pe_list;
}
+
+ return NULL;
}
static int
const Pointer_Event *pe1 = eina_list_data_get(data1);
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)
return 0;
else if (pe1->device < pe2->device)
_pointer_event_record(Taps_Type *st,
Eina_List *pe_list,
Pointer_Event *pe,
- Elm_Gesture_Layer_Smart_Data *sd,
+ Elm_Gesture_Layer_Data *sd,
void *event_info,
Evas_Callback_Type event_type)
{
/**
* @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 = 0, by = 0;
+ 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
+ *
* This function checks if the tap gesture is done.
*
* @param data gesture info pointer
* @ingroup Elm_Gesture_Layer
*/
static Eina_Bool
-_tap_gesture_check_finish(Gesture_Info *gesture)
+_tap_gesture_check_finish(Gesture_Info *gesture, Evas_Coord tap_finger_size)
{
/* Here we check if taps-gesture was completed successfuly */
- /* Count how many taps were recieved on each device then */
+ /* Count how many taps were received on each device then */
/* determine if it matches n_taps_needed defined on START */
+ unsigned int i;
Taps_Type *st = gesture->data;
Eina_List *l;
Eina_List *pe_list;
+ Evas_Coord_Rectangle base;
+ Evas_Coord_Rectangle tmp;
+ if (!tap_finger_size) /* Use system default if not set by user */
+ //TIZEN_ONLY(20180321): gesture layer needs their own tap area size to handle sensitivity.
+ //tap_finger_size = elm_config_finger_size_get();
+ tap_finger_size = _elm_config->glayer_tap_finger_size;
+ //
if (!st->l) return EINA_FALSE;
EINA_LIST_FOREACH(st->l, l, pe_list)
}
}
+ /* 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;
}
* @ingroup Elm_Gesture_Layer
*/
static void
-_tap_gesture_finish(void *data)
+_tap_gesture_finish(void *data, Evas_Coord tap_finger_size)
{
/* 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))
+ if (_tap_gesture_check_finish(gesture, tap_finger_size))
{
s = ELM_GESTURE_STATE_END;
}
ELM_GESTURE_LAYER_DATA_GET(data, sd);
if (IS_TESTED(ELM_GESTURE_N_TAPS))
- _tap_gesture_finish(sd->gesture[ELM_GESTURE_N_TAPS]);
+ _tap_gesture_finish(sd->gesture[ELM_GESTURE_N_TAPS],
+ sd->tap_finger_size);
if (IS_TESTED(ELM_GESTURE_N_DOUBLE_TAPS))
- _tap_gesture_finish(sd->gesture[ELM_GESTURE_N_DOUBLE_TAPS]);
+ _tap_gesture_finish(sd->gesture[ELM_GESTURE_N_DOUBLE_TAPS],
+ sd->tap_finger_size);
if (IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS))
- _tap_gesture_finish(sd->gesture[ELM_GESTURE_N_TRIPLE_TAPS]);
+ _tap_gesture_finish(sd->gesture[ELM_GESTURE_N_TRIPLE_TAPS],
+ sd->tap_finger_size);
_clear_if_finished(data);
sd->gest_taps_timeout = NULL;
_long_tap_timeout(void *data)
{
Gesture_Info *gesture = data;
+ Long_Tap_Type *st = gesture->data;
+
+ st->info.timestamp = ecore_time_get() * 1000;
_state_set(gesture, ELM_GESTURE_STATE_MOVE,
gesture->data, EINA_TRUE);
Taps_Type *st;
Gesture_Info *gesture;
Eina_List *pe_list = NULL;
- Pointer_Event *pe_down = NULL;
+ Pointer_Event *pe_last = NULL;
Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
/* Here we fill Tap struct */
switch (g_type)
{
case ELM_GESTURE_N_TAPS:
- taps = 1;
- break;
+ taps = 1;
+ break;
case ELM_GESTURE_N_DOUBLE_TAPS:
- taps = 2;
- break;
+ taps = 2;
+ break;
case ELM_GESTURE_N_TRIPLE_TAPS:
- taps = 3;
- break;
+ taps = 3;
+ break;
default:
- taps = 0;
- break;
+ taps = 0;
+ break;
}
st = gesture->data;
if (!st) /* Allocated once on first time */
{
st = calloc(1, sizeof(Taps_Type));
+ if (!st) return;
+
gesture->data = st;
_tap_gestures_test_reset(gesture);
}
{
case EVAS_CALLBACK_MULTI_DOWN:
case EVAS_CALLBACK_MOUSE_DOWN:
- /* Check if got tap on same cord was tapped before */
- pe_list = eina_list_search_unsorted(st->l, _match_fingers_compare, pe);
-
- if ((!pe_list) &&
- /* 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);
+ /* Each device taps (DOWN, UP event) registered in same list */
+ /* 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 (!_match_fingers_compare(st->l, pe, sd->tap_finger_size))
+ { /* 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);
- return;
- }
+ return;
+ }
+ }
- pe_list = _pointer_event_record
+ /* All tests are good, register this tap in device list */
+ pe_list = _pointer_event_record
(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 ((pe->device == 0) && (eina_list_count(pe_list) == 1))
- {
- ev_flag = _state_set(gesture, ELM_GESTURE_STATE_START,
- &st->info, EINA_FALSE);
- _event_consume(sd, event_info, event_type, ev_flag);
+ 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 /* 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;
- }
- 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);
+ st->n_taps_needed = taps * 2; /* count DOWN and UP */
- break;
+ return;
+ }
+ else if (eina_list_count(pe_list) > st->n_taps_needed)
+ { /* If we arleady got too many touches for this gesture. */
+ _state_set(gesture, ELM_GESTURE_STATE_ABORT,
+ &st->info, EINA_FALSE);
+ }
+
+ if (gesture->state == ELM_GESTURE_STATE_MOVE)
+ { /* Report MOVE if all devices have same DOWN/UP count */
+ /* Should be in MOVE state from last UP event */
+ Eina_List *l;
+ Eina_Bool move = EINA_TRUE;
+ unsigned int n = 0;
+
+ EINA_LIST_FOREACH(st->l, l, pe_list)
+ {
+ if (n == 0)
+ {
+ n = eina_list_count(pe_list);
+ }
+ else if (n != eina_list_count(pe_list))
+ {
+ move = EINA_FALSE;
+ }
+ }
+
+ if (move && (n > 0))
+ {
+ _state_set(gesture, ELM_GESTURE_STATE_MOVE,
+ &st->info, EINA_TRUE);
+ }
+ }
+
+ break;
case EVAS_CALLBACK_MULTI_UP:
case EVAS_CALLBACK_MOUSE_UP:
- pe_list = eina_list_search_unsorted(st->l, _pe_device_compare, pe);
- if (!pe_list) return;
+ pe_list = eina_list_search_unsorted(st->l, _pe_device_compare, pe);
+ if (!pe_list) return;
+
+ _pointer_event_record(st, pe_list, pe, sd, 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)))
+ { /* Test for finish immidiatly, not waiting for timeout */
+ if (_tap_gesture_check_finish(gesture, sd->tap_finger_size))
+ {
+ _tap_gesture_finish(gesture, sd->tap_finger_size);
+ return;
+ }
+ }
- pe_list = _pointer_event_record
- (st, pe_list, pe, sd, event_info, event_type);
+ if ((gesture->state == ELM_GESTURE_STATE_START) ||
+ (gesture->state == ELM_GESTURE_STATE_MOVE))
+ { /* Tap gesture started, no finger on surface. Report MOVE */
+ Eina_List *l;
+ Eina_Bool move = EINA_TRUE;
+ unsigned int n = 0;
- 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;
- }
- }
+ /* Report move only if all devices have same DOWN/UP count */
+ EINA_LIST_FOREACH(st->l, l, pe_list)
+ {
+ if (n == 0)
+ {
+ n = eina_list_count(pe_list);
+ }
+ else if (n != eina_list_count(pe_list))
+ {
+ move = EINA_FALSE;
+ }
+ }
- break;
+ if ((move && (n > 0)) && (n < st->n_taps_needed))
+ { /* Set number of fingers and report MOVE */
+ /* We don't report MOVE when (n >= st->n_taps_needed)
+ because will be END or ABORT at this stage */
+ st->info.n = eina_list_count(st->l);
+ _state_set(gesture, ELM_GESTURE_STATE_MOVE,
+ &st->info, EINA_TRUE);
+ }
+ }
+
+ break;
case EVAS_CALLBACK_MULTI_MOVE:
case EVAS_CALLBACK_MOUSE_MOVE:
- /* Get first event in first list, this has to be a Mouse Down event */
- /* and verify that user didn't move out of this area before next tap */
- pe_list = eina_list_search_unsorted(st->l, _pe_device_compare, pe);
- if (pe_list)
- {
- pe_down = eina_list_data_get(pe_list);
- if (!_inside(pe_down->x, pe_down->y, pe->x, pe->y))
- {
- ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
- &st->info, EINA_FALSE);
- _event_consume(sd, event_info, event_type, ev_flag);
- }
- }
- break;
+ /* Verify that user didn't move out of tap area before next tap */
+ /* BUT: we need to skip some MOVE events coming before DOWN */
+ /* when user taps next tap. So fetch LAST recorded event for */
+ /* device (DOWN or UP event), ignore all MOVEs if last was UP */
+ pe_last = eina_list_data_get(eina_list_last(
+ eina_list_search_unsorted(st->l, _pe_device_compare, pe)));
+
+ if (pe_last)
+ { /* pe_last is the last event recorded for this device */
+ if ((pe_last->event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
+ (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,
+ sd->tap_finger_size))
+ {
+ ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
+ &st->info, EINA_FALSE);
+ _event_consume(sd, event_info, event_type, ev_flag);
+ }
+ }
+ }
+ break;
default:
- return;
+ return;
}
}
if (!st) /* Allocated once on first time */
{
st = calloc(1, sizeof(Long_Tap_Type));
+ if (!st) return;
+
gesture->data = st;
_n_long_tap_test_reset(gesture);
}
_compute_taps_center(st, &st->info.x, &st->info.y, pe);
st->center_x = st->info.x; /* Update coords for */
st->center_y = st->info.y; /* reporting START */
+ st->info.timestamp = pe->timestamp;
/* This is the first mouse down we got */
if (eina_list_count(st->touched) == 1)
{
_state_set(gesture, ELM_GESTURE_STATE_START,
gesture->data, EINA_FALSE);
- st->info.timestamp = pe->timestamp;
/* To test long tap */
/* When this timer expires, gesture STARTED */
case EVAS_CALLBACK_MOUSE_UP:
st->touched = _touched_device_remove(st->touched, pe);
_compute_taps_center(st, &st->center_x, &st->center_y, pe);
+ st->info.timestamp = pe->timestamp;
if (st->info.n)
{
if (gesture->state == ELM_GESTURE_STATE_MOVE)
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
&st->info, EINA_FALSE);
- if (st->timeout)
- {
- ecore_timer_del(st->timeout);
- st->timeout = NULL;
- }
+ ELM_SAFE_FREE(st->timeout, ecore_timer_del);
_event_consume(sd, event_info, event_type, ev_flag);
}
Evas_Coord y = 0;
_compute_taps_center(st, &x, &y, pe);
+ st->info.timestamp = pe->timestamp;
/* ABORT if user moved fingers out of tap area */
- if (!_inside(x, y, st->center_x, st->center_y))
+ if (!_inside(x, y, st->center_x, st->center_y,
+ sd->tap_finger_size))
{
- if (st->timeout)
- {
- ecore_timer_del(st->timeout);
- st->timeout = NULL;
- }
+ ELM_SAFE_FREE(st->timeout, ecore_timer_del);
/* Report MOVE if gesture started */
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
* This momentum value will be sent to widget when gesture is completed.
*
* @param momentum pointer to buffer where we record momentum value.
- * @param x1 x coord where user started gesture.
- * @param y1 y coord where user started gesture.
- * @param x2 x coord where user completed gesture.
- * @param y2 y coord where user completed gesture.
+ * @param xx1 x coord where user started gesture.
+ * @param yy1 y coord where user started gesture.
+ * @param xx2 x coord where user completed gesture.
+ * @param yy2 y coord where user completed gesture.
* @param t1x timestamp for X, when user started gesture.
* @param t1y timestamp for Y, when user started gesture.
* @param t2 timestamp when user completed gesture.
*
* This function is used for computing rotation angle (DEG).
*
- * @param x1 first finger x location.
- * @param y1 first finger y location.
- * @param x2 second finger x location.
- * @param y2 second finger y location.
+ * @param xx1 first finger x location.
+ * @param yy1 first finger y location.
+ * @param xx2 second finger x location.
+ * @param yy2 second finger y location.
*
- * @return angle of the line between (x1,y1), (x2,y2) in Deg.
+ * @return angle of the line between (xx1,yy1), (xx2,yy2) in Deg.
* Angles now are given in DEG, not RAD.
* ZERO angle at 12-oclock, growing clockwise.
*
{
double a, xx, yy, rt = (-1);
- xx = fabs(xx2 - xx1);
- yy = fabs(yy2 - yy1);
+ xx = abs(xx2 - xx1);
+ yy = abs(yy2 - yy1);
if (((int)xx) && ((int)yy))
{
* This function is used for computing the magnitude and direction
* of vector between two points.
*
- * @param x1 first finger x location.
- * @param y1 first finger y location.
- * @param x2 second finger x location.
- * @param y2 second finger y location.
+ * @param xx1 first finger x location.
+ * @param yy1 first finger y location.
+ * @param xx2 second finger x location.
+ * @param yy2 second finger y location.
* @param l length computed (output)
* @param a angle computed (output)
*
if (!st) /* Allocated once on first time */
{
st = calloc(1, sizeof(Momentum_Type));
+ if (!st) return;
+
gesture->data = st;
_momentum_test_reset(gesture);
}
st->line_end.y = pe_local.y;
st->t_end = pe_local.timestamp;
- if ((fabs(st->info.mx) > ELM_GESTURE_MINIMUM_MOMENTUM) ||
- (fabs(st->info.my) > ELM_GESTURE_MINIMUM_MOMENTUM))
+ if ((abs(st->info.mx) > ELM_GESTURE_MINIMUM_MOMENTUM) ||
+ (abs(st->info.my) > ELM_GESTURE_MINIMUM_MOMENTUM))
state_to_report = ELM_GESTURE_STATE_END;
else
state_to_report = ELM_GESTURE_STATE_ABORT;
if (!st)
{
st = calloc(1, sizeof(Line_Type));
+ if (!st) return;
+
gesture->data = st;
}
* This function is used for computing the gap between fingers.
* It returns the length and center point between fingers.
*
- * @param x1 first finger x location.
- * @param y1 first finger y location.
- * @param x2 second finger x location.
- * @param y2 second finger y location.
- * @param x Gets center point x cord (output)
- * @param y Gets center point y cord (output)
+ * @param xx1 first finger x location.
+ * @param yy1 first finger y location.
+ * @param xx2 second finger x location.
+ * @param yy2 second finger y location.
+ * @param x Get center point x cord (output)
+ * @param y Get center point y cord (output)
*
- * @return length of the line between (x1,y1), (x2,y2) in pixels.
+ * @return length of the line between (xx1,yy1), (xx2,yy2) in pixels.
*
* @ingroup Elm_Gesture_Layer
*/
Evas_Coord *y)
{
double a, b, xx, yy, gap;
- xx = fabs(xx2 - xx1);
- yy = fabs(yy2 - yy1);
+ xx = abs(xx2 - xx1);
+ yy = abs(yy2 - yy1);
gap = sqrt((xx * xx) + (yy * yy));
/* START - Compute zoom center point */
* This function is used for computing zoom value.
*
* @param st Pointer to zoom data based on user input.
- * @param x1 first finger x location.
- * @param y1 first finger y location.
- * @param x2 second finger x location.
- * @param y2 second finger y location.
+ * @param xx1 first finger x location.
+ * @param yy1 first finger y location.
+ * @param xx2 second finger x location.
+ * @param yy2 second finger y location.
* @param factor zoom-factor, used to determine how fast zoom works.
*
* @return zoom value, when 1.0 means no zoom, 0.5 half size...
if (!st) /* Allocated once on first time, used for zoom intermediate data */
{
st = calloc(1, sizeof(Zoom_Type));
+ if (!st) return;
+
gesture_zoom->data = st;
_zoom_test_reset(gesture_zoom);
}
case EVAS_CALLBACK_KEY_UP:
{
Evas_Event_Key_Up *p = event_info;
- if ((!strcmp(p->keyname, "Control_L")) ||
+ if ((!strcmp(p->key, "Control_L")) ||
/* Test if we ended a zoom gesture when releasing CTRL */
- (!strcmp(p->keyname, "Control_R")))
+ (!strcmp(p->key, "Control_R")))
{
if ((st->zoom_wheel) &&
((gesture_zoom->state == ELM_GESTURE_STATE_START) ||
if (!st) /* Allocated once on first time, used for zoom data */
{
st = calloc(1, sizeof(Zoom_Type));
+ if (!st) return;
+
gesture_zoom->data = st;
_zoom_test_reset(gesture_zoom);
}
if ((!sd->glayer_continues_enable) &&
(!st->zoom_st.timestamp))
return;
-
+ // fallthrough is intentional
case EVAS_CALLBACK_MOUSE_DOWN:
case EVAS_CALLBACK_MULTI_DOWN:
{ /* Here we take care of zoom-start and zoom move */
if (!st) /* Allocated once on first time */
{
st = calloc(1, sizeof(Rotate_Type));
+ if (!st) return;
+
gesture->data = st;
_rotate_test_reset(gesture);
}
if ((!sd->glayer_continues_enable) &&
(!st->rotate_st.timestamp))
return;
-
+ // fallthrough is intentional
case EVAS_CALLBACK_MOUSE_DOWN:
case EVAS_CALLBACK_MULTI_DOWN:
{ /* Here we take care of rotate-start and rotate move */
}
}
-static void
-_elm_gesture_layer_smart_disable(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
+EOLIAN static Eina_Bool
+_elm_gesture_layer_elm_widget_disable(Eo *obj, Elm_Gesture_Layer_Data *_pd EINA_UNUSED)
{
- Eina_Bool *ret = va_arg(*list, Eina_Bool *);
if (elm_widget_disabled_get(obj))
_callbacks_unregister(obj);
else
_callbacks_register(obj);
- if (ret) *ret = EINA_TRUE;
+ return EINA_TRUE;
}
-static void
-_elm_gesture_layer_smart_add(Eo *obj, void *_pd, va_list *list EINA_UNUSED)
+EOLIAN static void
+_elm_gesture_layer_evas_object_smart_add(Eo *obj, Elm_Gesture_Layer_Data *priv)
{
- eo_do_super(obj, evas_obj_smart_add());
-
- Elm_Gesture_Layer_Smart_Data *priv = _pd;
+ eo_do_super(obj, MY_CLASS, evas_obj_smart_add());
+ elm_widget_sub_object_parent_add(obj);
priv->line_min_length =
_elm_config->glayer_line_min_length * elm_config_finger_size_get();
memset(priv->gesture, 0, sizeof(priv->gesture));
}
-static void
-_elm_gesture_layer_smart_del(Eo *obj, void *_pd, va_list *list EINA_UNUSED)
+static void _cbs_clean(Elm_Gesture_Layer_Data *sd, Elm_Gesture_Type idx, Elm_Gesture_State cb_type);
+
+EOLIAN static void
+_elm_gesture_layer_evas_object_smart_del(Eo *obj, Elm_Gesture_Layer_Data *sd)
{
- Elm_Gesture_Layer_Smart_Data *sd = _pd;
Pointer_Event *data;
int i;
- _event_history_clear(obj);
- eina_list_free(sd->pending);
-
- EINA_LIST_FREE(sd->touched, data)
- free(data);
-
- if (!elm_widget_disabled_get(obj))
- _callbacks_unregister(obj);
+ /* Clear all gestures intermediate data, stop any timers */
+ {
+ /* FIXME: +1 because of the mistake in the enum. */
+ Gesture_Info **gitr = sd->gesture + 1;
+ Tests_Array_Funcs *fitr = _glayer_tests_array + 1;
+ for (; fitr->reset; fitr++, gitr++)
+ {
+ if (IS_TESTED_GESTURE(*gitr))
+ fitr->reset(*gitr);
+ }
+ }
- /* Free all gestures internal data structures */
+ /* First Free all gestures internal data structures */
for (i = 0; i < ELM_GESTURE_LAST; i++)
if (sd->gesture[i])
{
if (sd->gesture[i]->data)
free(sd->gesture[i]->data);
+ _cbs_clean(sd, i, ELM_GESTURE_STATE_START);
+ _cbs_clean(sd, i, ELM_GESTURE_STATE_MOVE);
+ _cbs_clean(sd, i, ELM_GESTURE_STATE_END);
+ _cbs_clean(sd, i, ELM_GESTURE_STATE_ABORT);
free(sd->gesture[i]);
+ sd->gesture[i] = NULL; /* Referenced by _event_history_clear */
}
+ ecore_timer_del(sd->gest_taps_timeout);
+
+ /* Then take care of clearing events */
+ _event_history_clear(obj);
+ sd->pending = eina_list_free(sd->pending);
+
+ EINA_LIST_FREE(sd->touched, data)
+ free(data);
- eo_do_super(obj, evas_obj_smart_del());
+ if (!elm_widget_disabled_get(obj))
+ _callbacks_unregister(obj);
+
+ eo_do_super(obj, MY_CLASS, evas_obj_smart_del());
}
EAPI Evas_Object *
{
EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
Evas_Object *obj = eo_add(MY_CLASS, parent);
- eo_unref(obj);
return obj;
}
-static void
-_constructor(Eo *obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+EOLIAN static Eo *
+_elm_gesture_layer_eo_base_constructor(Eo *obj, Elm_Gesture_Layer_Data *_pd EINA_UNUSED)
{
- eo_do_super(obj, eo_constructor());
- eo_do(obj, evas_obj_type_set(MY_CLASS_NAME));
+ obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
+ eo_do(obj, evas_obj_type_set(MY_CLASS_NAME_LEGACY));
- if (!elm_widget_sub_object_add(eo_parent_get(obj), obj))
- ERR("could not add %p as sub object of %p", obj, eo_parent_get(obj));
-}
-
-EAPI Eina_Bool
-elm_gesture_layer_hold_events_get(const Evas_Object *obj)
-{
- ELM_GESTURE_LAYER_CHECK(obj) EINA_FALSE;
- Eina_Bool ret = EINA_FALSE;
- eo_do((Eo *) obj, elm_obj_gesture_layer_hold_events_get(&ret));
- return ret;
-}
-
-static void
-_hold_events_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
-{
- Eina_Bool *ret = va_arg(*list, Eina_Bool *);
- Elm_Gesture_Layer_Smart_Data *sd = _pd;
- *ret = !sd->repeat_events;
+ return obj;
}
-EAPI void
-elm_gesture_layer_hold_events_set(Evas_Object *obj,
- Eina_Bool hold_events)
+EOLIAN static Eina_Bool
+_elm_gesture_layer_hold_events_get(Eo *obj EINA_UNUSED, Elm_Gesture_Layer_Data *sd)
{
- ELM_GESTURE_LAYER_CHECK(obj);
- eo_do(obj, elm_obj_gesture_layer_hold_events_set(hold_events));
+ return !sd->repeat_events;
}
-static void
-_hold_events_set(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+EOLIAN static void
+_elm_gesture_layer_hold_events_set(Eo *obj EINA_UNUSED, Elm_Gesture_Layer_Data *sd, Eina_Bool hold_events)
{
- Eina_Bool hold_events = va_arg(*list, int);
- Elm_Gesture_Layer_Smart_Data *sd = _pd;
-
sd->repeat_events = !(!!hold_events);
}
-EAPI double
-elm_gesture_layer_zoom_step_get(const Evas_Object *obj)
-{
- ELM_GESTURE_LAYER_CHECK(obj) 0;
- double ret = 0;
- eo_do((Eo *) obj, elm_obj_gesture_layer_zoom_step_get(&ret));
- return ret;
-}
-
-static void
-_zoom_step_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
-{
- double *ret = va_arg(*list, double *);
- Elm_Gesture_Layer_Smart_Data *sd = _pd;
- *ret = sd->zoom_step;
-}
-
-EAPI void
-elm_gesture_layer_zoom_step_set(Evas_Object *obj,
- double step)
+EOLIAN static double
+_elm_gesture_layer_zoom_step_get(Eo *obj EINA_UNUSED, Elm_Gesture_Layer_Data *sd)
{
- ELM_GESTURE_LAYER_CHECK(obj);
- eo_do(obj, elm_obj_gesture_layer_zoom_step_set(step));
+ return sd->zoom_step;
}
-static void
-_zoom_step_set(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+EOLIAN static void
+_elm_gesture_layer_zoom_step_set(Eo *obj EINA_UNUSED, Elm_Gesture_Layer_Data *sd, double step)
{
- double step = va_arg(*list, double);
- Elm_Gesture_Layer_Smart_Data *sd = _pd;
-
if (step < 0) return;
sd->zoom_step = step;
}
-EAPI double
-elm_gesture_layer_rotate_step_get(const Evas_Object *obj)
+EOLIAN static double
+_elm_gesture_layer_rotate_step_get(Eo *obj EINA_UNUSED, Elm_Gesture_Layer_Data *sd)
{
- ELM_GESTURE_LAYER_CHECK(obj) 0;
- double ret = 0;
- eo_do((Eo *) obj, elm_obj_gesture_layer_rotate_step_get(&ret));
- return ret;
+ return sd->rotate_step;
}
-static void
-_rotate_step_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+EOLIAN static void
+_elm_gesture_layer_rotate_step_set(Eo *obj EINA_UNUSED, Elm_Gesture_Layer_Data *sd, double step)
{
- double *ret = va_arg(*list, double *);
- Elm_Gesture_Layer_Smart_Data *sd = _pd;
- *ret = sd->rotate_step;
-}
-
-EAPI void
-elm_gesture_layer_rotate_step_set(Evas_Object *obj,
- double step)
-{
- ELM_GESTURE_LAYER_CHECK(obj);
- eo_do(obj, elm_obj_gesture_layer_rotate_step_set(step));
-}
-
-static void
-_rotate_step_set(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
-{
- double step = va_arg(*list, double);
- Elm_Gesture_Layer_Smart_Data *sd = _pd;
-
if (step < 0) return;
sd->rotate_step = step;
}
-EAPI Eina_Bool
-elm_gesture_layer_attach(Evas_Object *obj,
- Evas_Object *target)
+EOLIAN static Eina_Bool
+_elm_gesture_layer_attach(Eo *obj, Elm_Gesture_Layer_Data *sd, Evas_Object *target)
{
- ELM_GESTURE_LAYER_CHECK(obj) EINA_FALSE;
- Eina_Bool ret = EINA_FALSE;
- eo_do(obj, elm_obj_gesture_layer_attach(target, &ret));
- return ret;
-}
-
-static void
-_attach(Eo *obj, void *_pd, va_list *list)
-{
- Evas_Object *target = va_arg(*list, Evas_Object *);
- Eina_Bool *ret = va_arg(*list, Eina_Bool *);
- Elm_Gesture_Layer_Smart_Data *sd = _pd;
- if (ret) *ret = EINA_FALSE;
-
- if (!target) return;
+ if (!target) return EINA_FALSE;
/* if was attached before, unregister callbacks first */
if (sd->target)
sd->target = target;
_callbacks_register(obj);
- if (ret) *ret = EINA_TRUE;
+ return EINA_TRUE;
}
-EAPI void
-elm_gesture_layer_cb_set(Evas_Object *obj,
- Elm_Gesture_Type idx,
- Elm_Gesture_State cb_type,
- Elm_Gesture_Event_Cb cb,
- void *data)
+static void
+_cbs_clean(Elm_Gesture_Layer_Data *sd,
+ Elm_Gesture_Type idx,
+ Elm_Gesture_State cb_type)
{
- ELM_GESTURE_LAYER_CHECK(obj);
- eo_do(obj, elm_obj_gesture_layer_cb_set(idx, cb_type, cb, data));
+ if (!sd->gesture[idx]) return;
+
+ Func_Data *cb_info;
+ EINA_INLIST_FREE(sd->gesture[idx]->cbs[cb_type], cb_info)
+ {
+ sd->gesture[idx]->cbs[cb_type] = eina_inlist_remove(
+ sd->gesture[idx]->cbs[cb_type], EINA_INLIST_GET(cb_info));
+ free(cb_info);
+ }
+ SET_TEST_BIT(sd->gesture[idx]);
}
-static void
-_cb_set(Eo *obj, void *_pd, va_list *list)
+EOLIAN static void
+_elm_gesture_layer_cb_set(Eo *obj, Elm_Gesture_Layer_Data *sd, Elm_Gesture_Type idx, Elm_Gesture_State cb_type, Elm_Gesture_Event_Cb cb, void *data)
{
- Elm_Gesture_Type idx = va_arg(*list, Elm_Gesture_Type);
- Elm_Gesture_State cb_type = va_arg(*list, Elm_Gesture_State);
- Elm_Gesture_Event_Cb cb = va_arg(*list, Elm_Gesture_Event_Cb);
- void *data = va_arg(*list, void *);
+ /* Clear gesture intermediate data, stop any timers */
+ if (IS_TESTED_GESTURE(sd->gesture[idx]))
+ _glayer_tests_array[idx].reset(sd->gesture[idx]);
+
+ _cbs_clean(sd, idx, cb_type); // for ABI compat.
+ eo_do(obj, elm_obj_gesture_layer_cb_add(idx, cb_type, cb, data));
+}
+
+EOLIAN static void
+_elm_gesture_layer_cb_add(Eo *obj, Elm_Gesture_Layer_Data *sd, Elm_Gesture_Type idx, Elm_Gesture_State cb_type, Elm_Gesture_Event_Cb cb, void *data)
+{
+ if (!cb) return;
Gesture_Info *p;
- Elm_Gesture_Layer_Smart_Data *sd = _pd;
if (!sd->gesture[idx])
sd->gesture[idx] = calloc(1, sizeof(Gesture_Info));
if (!sd->gesture[idx]) return;
+ Func_Data *cb_info = calloc(1, sizeof(*cb_info));
+ if (!cb_info) return;
+ cb_info->cb = cb;
+ cb_info->user_data = data;
+
p = sd->gesture[idx];
p->obj = obj;
p->g_type = idx;
- p->fn[cb_type].cb = cb;
- p->fn[cb_type].user_data = data;
+ p->cbs[cb_type] = eina_inlist_append(p->cbs[cb_type],
+ EINA_INLIST_GET(cb_info));
p->state = ELM_GESTURE_STATE_UNDEFINED;
SET_TEST_BIT(p);
}
+EOLIAN static void
+_elm_gesture_layer_cb_del(Eo *obj EINA_UNUSED, Elm_Gesture_Layer_Data *sd, Elm_Gesture_Type idx, Elm_Gesture_State cb_type, Elm_Gesture_Event_Cb cb, void *data)
+{
+ if (!sd->gesture[idx]) return;
+
+ Eina_Inlist *itr;
+ Func_Data *cb_info;
+ EINA_INLIST_FOREACH_SAFE(sd->gesture[idx]->cbs[cb_type], itr, cb_info)
+ {
+ if (cb_info->cb == cb && cb_info->user_data == data)
+ {
+ /* Clear gesture intermediate data, stop any timers */
+ if (IS_TESTED_GESTURE(sd->gesture[idx]))
+ _glayer_tests_array[idx].reset(sd->gesture[idx]);
+
+ sd->gesture[idx]->cbs[cb_type] = eina_inlist_remove(
+ sd->gesture[idx]->cbs[cb_type], EINA_INLIST_GET(cb_info));
+ free(cb_info);
+ SET_TEST_BIT(sd->gesture[idx]);
+ return;
+ }
+ }
+}
+
EAPI void
elm_gesture_layer_line_min_length_set(Evas_Object *obj, int line_min_length)
{
sd->line_min_length = line_min_length;
}
-
EAPI int
elm_gesture_layer_line_min_length_get(const Evas_Object *obj)
{
return sd->double_tap_timeout;
}
-static void
-_class_constructor(Eo_Class *klass)
-{
- const Eo_Op_Func_Description func_desc[] = {
- EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_CONSTRUCTOR), _constructor),
-
- EO_OP_FUNC(EVAS_OBJ_SMART_ID(EVAS_OBJ_SMART_SUB_ID_ADD), _elm_gesture_layer_smart_add),
- EO_OP_FUNC(EVAS_OBJ_SMART_ID(EVAS_OBJ_SMART_SUB_ID_DEL), _elm_gesture_layer_smart_del),
-
- EO_OP_FUNC(ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_DISABLE), _elm_gesture_layer_smart_disable),
-
- EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_HOLD_EVENTS_GET), _hold_events_get),
- EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_HOLD_EVENTS_SET), _hold_events_set),
- EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_ZOOM_STEP_GET), _zoom_step_get),
- EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_ZOOM_STEP_SET), _zoom_step_set),
- EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_ROTATE_STEP_GET), _rotate_step_get),
- EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_ROTATE_STEP_SET), _rotate_step_set),
- EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_ATTACH), _attach),
- EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_CB_SET), _cb_set),
- EO_OP_FUNC_SENTINEL
- };
- eo_class_funcs_set(klass, func_desc);
-
- evas_smart_legacy_type_register(MY_CLASS_NAME, klass);
-}
-
-static const Eo_Op_Description op_desc[] = {
- EO_OP_DESCRIPTION(ELM_OBJ_GESTURE_LAYER_SUB_ID_HOLD_EVENTS_GET, "Call this function to get repeat-events settings."),
- EO_OP_DESCRIPTION(ELM_OBJ_GESTURE_LAYER_SUB_ID_HOLD_EVENTS_SET, "This function is to make gesture-layer repeat events."),
- EO_OP_DESCRIPTION(ELM_OBJ_GESTURE_LAYER_SUB_ID_ZOOM_STEP_GET, "This function returns step-value for zoom action."),
- EO_OP_DESCRIPTION(ELM_OBJ_GESTURE_LAYER_SUB_ID_ZOOM_STEP_SET, "This function sets step-value for zoom action."),
- EO_OP_DESCRIPTION(ELM_OBJ_GESTURE_LAYER_SUB_ID_ROTATE_STEP_GET, "This function returns step-value for rotate action."),
- EO_OP_DESCRIPTION(ELM_OBJ_GESTURE_LAYER_SUB_ID_ROTATE_STEP_SET, "This function sets step-value for rotate action."),
- 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."),
- 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."),
- EO_OP_DESCRIPTION_SENTINEL
-};
+EOLIAN static void
+_elm_gesture_layer_tap_finger_size_set(Eo *obj EINA_UNUSED, Elm_Gesture_Layer_Data *sd, Evas_Coord sz)
+{
+ if (sz < 0)
+ sz = 0; /* Should not be negative, will reset to system value */
-static const Eo_Class_Description class_desc = {
- EO_VERSION,
- MY_CLASS_NAME,
- EO_CLASS_TYPE_REGULAR,
- EO_CLASS_DESCRIPTION_OPS(&ELM_OBJ_GESTURE_LAYER_BASE_ID, op_desc, ELM_OBJ_GESTURE_LAYER_SUB_ID_LAST),
- NULL,
- sizeof(Elm_Gesture_Layer_Smart_Data),
- _class_constructor,
- NULL
-};
+ sd->tap_finger_size = sz;
+}
+
+EOLIAN static Evas_Coord
+_elm_gesture_layer_tap_finger_size_get(Eo *obj EINA_UNUSED, Elm_Gesture_Layer_Data *sd)
+{
+ return sd->tap_finger_size;
+}
+
+static void
+_elm_gesture_layer_class_constructor(Eo_Class *klass)
+{
+ evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
+}
-EO_DEFINE_CLASS(elm_obj_gesture_layer_class_get, &class_desc, ELM_OBJ_WIDGET_CLASS, NULL);
+#include "elm_gesture_layer.eo.c"