forked from enlightenment/efl
Gesture Layer: support multiple callbacks per type/state.
elm_gesture_layer_cb_add/del functions have been added to provide this functionality. elm_gesture_layer_cb_set provided only one callback and so was overriding the callback with the new one. For ABI compatibility, some rules were needed: - when set function is called with NULL, all the callbacks of the state will be removed (old behavior respect) - try to use set or add/del exclusively with a preference to the new APIs. This is because of the first rule and because it will be more correct. - if you remove a callback, only one instance of this callback of this type/state for this gesture will be removed, by comparing func and data. It means that if you register twice the same callback/data, it will be added twice and you will have to remove also twice too.
This commit is contained in:
parent
61dd0ba0ba
commit
e49de4c97b
|
@ -1458,3 +1458,8 @@
|
|||
2013-06-25 Ryuan Choi (ryuan)
|
||||
|
||||
* Fix crash of elm_notify when timeout is zero.
|
||||
|
||||
2013-06-26 Daniel Zaoui (JackDanielZ)
|
||||
|
||||
* Gesture Layer: add APIs to add/del multiple callbacks for a same
|
||||
gesture/type/state.
|
||||
|
|
|
@ -44,10 +44,10 @@ _glayer_buf_dup(void *buf, size_t size)
|
|||
|
||||
#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) \
|
||||
|
@ -118,6 +118,7 @@ typedef struct _Pointer_Event Pointer_Event;
|
|||
*/
|
||||
struct _Func_Data
|
||||
{
|
||||
EINA_INLIST;
|
||||
void *user_data; /**< Holds user data to CB (like sd) */
|
||||
Elm_Gesture_Event_Cb cb;
|
||||
};
|
||||
|
@ -144,7 +145,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 */
|
||||
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 */
|
||||
|
@ -606,14 +607,16 @@ static Evas_Event_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
|
||||
(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;
|
||||
|
@ -3704,6 +3707,8 @@ _elm_gesture_layer_smart_add(Eo *obj, void *_pd, va_list *list EINA_UNUSED)
|
|||
memset(priv->gesture, 0, sizeof(priv->gesture));
|
||||
}
|
||||
|
||||
static void _cbs_clean(Elm_Gesture_Layer_Smart_Data *sd, Elm_Gesture_Type idx, Elm_Gesture_State cb_type);
|
||||
|
||||
static void
|
||||
_elm_gesture_layer_smart_del(Eo *obj, void *_pd, va_list *list EINA_UNUSED)
|
||||
{
|
||||
|
@ -3727,6 +3732,10 @@ _elm_gesture_layer_smart_del(Eo *obj, void *_pd, va_list *list EINA_UNUSED)
|
|||
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]);
|
||||
}
|
||||
if (sd->gest_taps_timeout) ecore_timer_del(sd->gest_taps_timeout);
|
||||
|
@ -3888,6 +3897,23 @@ _attach(Eo *obj, void *_pd, va_list *list)
|
|||
if (ret) *ret = EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_cbs_clean(Elm_Gesture_Layer_Smart_Data *sd,
|
||||
Elm_Gesture_Type idx,
|
||||
Elm_Gesture_State cb_type)
|
||||
{
|
||||
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]);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
elm_gesture_layer_cb_set(Evas_Object *obj,
|
||||
Elm_Gesture_Type idx,
|
||||
|
@ -3907,6 +3933,33 @@ _cb_set(Eo *obj, void *_pd, va_list *list)
|
|||
Elm_Gesture_Event_Cb cb = va_arg(*list, Elm_Gesture_Event_Cb);
|
||||
void *data = va_arg(*list, void *);
|
||||
|
||||
Elm_Gesture_Layer_Smart_Data *sd = _pd;
|
||||
|
||||
_cbs_clean(sd, idx, cb_type); // for ABI compat.
|
||||
eo_do(obj, elm_obj_gesture_layer_cb_add(idx, cb_type, cb, data));
|
||||
}
|
||||
|
||||
EAPI void
|
||||
elm_gesture_layer_cb_add(Evas_Object *obj,
|
||||
Elm_Gesture_Type idx,
|
||||
Elm_Gesture_State cb_type,
|
||||
Elm_Gesture_Event_Cb cb,
|
||||
void *data)
|
||||
{
|
||||
ELM_GESTURE_LAYER_CHECK(obj);
|
||||
eo_do(obj, elm_obj_gesture_layer_cb_add(idx, cb_type, cb, data));
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_add(Eo *obj, void *_pd, va_list *list)
|
||||
{
|
||||
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 *);
|
||||
|
||||
if (!cb) return;
|
||||
|
||||
Gesture_Info *p;
|
||||
Elm_Gesture_Layer_Smart_Data *sd = _pd;
|
||||
|
||||
|
@ -3914,15 +3967,58 @@ _cb_set(Eo *obj, void *_pd, va_list *list)
|
|||
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);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
elm_gesture_layer_cb_del(Evas_Object *obj,
|
||||
Elm_Gesture_Type idx,
|
||||
Elm_Gesture_State cb_type,
|
||||
Elm_Gesture_Event_Cb cb,
|
||||
void *data)
|
||||
{
|
||||
ELM_GESTURE_LAYER_CHECK(obj);
|
||||
eo_do(obj, elm_obj_gesture_layer_cb_del(idx, cb_type, cb, data));
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_del(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
|
||||
{
|
||||
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 *);
|
||||
|
||||
Elm_Gesture_Layer_Smart_Data *sd = _pd;
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
@ -4158,6 +4254,8 @@ _class_constructor(Eo_Class *klass)
|
|||
EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_CB_SET), _cb_set),
|
||||
EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_TAP_FINGER_SIZE_SET), _tap_finger_size_set),
|
||||
EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_TAP_FINGER_SIZE_GET), _tap_finger_size_get),
|
||||
EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_CB_ADD), _cb_add),
|
||||
EO_OP_FUNC(ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_CB_DEL), _cb_del),
|
||||
EO_OP_FUNC_SENTINEL
|
||||
};
|
||||
eo_class_funcs_set(klass, func_desc);
|
||||
|
@ -4176,6 +4274,8 @@ static const Eo_Op_Description op_desc[] = {
|
|||
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(ELM_OBJ_GESTURE_LAYER_TAP_FINGER_SIZE_SET, "Use function to set valid touch-area size for finger."),
|
||||
EO_OP_DESCRIPTION(ELM_OBJ_GESTURE_LAYER_TAP_FINGER_SIZE_GET, "This function returns the valid touch-area size for finger."),
|
||||
EO_OP_DESCRIPTION(ELM_OBJ_GESTURE_LAYER_SUB_ID_CB_ADD, "Use function to add callbacks to be notified about change of state of gesture."),
|
||||
EO_OP_DESCRIPTION(ELM_OBJ_GESTURE_LAYER_SUB_ID_CB_DEL, "Use function to remove added callbacks."),
|
||||
EO_OP_DESCRIPTION_SENTINEL
|
||||
};
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@ enum
|
|||
ELM_OBJ_GESTURE_LAYER_SUB_ID_CB_SET,
|
||||
ELM_OBJ_GESTURE_LAYER_TAP_FINGER_SIZE_SET,
|
||||
ELM_OBJ_GESTURE_LAYER_TAP_FINGER_SIZE_GET,
|
||||
ELM_OBJ_GESTURE_LAYER_SUB_ID_CB_ADD,
|
||||
ELM_OBJ_GESTURE_LAYER_SUB_ID_CB_DEL,
|
||||
ELM_OBJ_GESTURE_LAYER_SUB_ID_LAST
|
||||
};
|
||||
|
||||
|
@ -127,7 +129,10 @@ enum
|
|||
* @since 1.8
|
||||
*
|
||||
* Use function to set callbacks to be notified about
|
||||
* change of state of gesture.
|
||||
* change of state of gesture. If a function was already
|
||||
* set for this gesture/type/state, it will be replaced by the new one.
|
||||
* For ABI compat, callbacks added by elm_obj_gesture_layer_cb_add will be removed. It is recommended
|
||||
* to use only one of these functions for a gesture object.
|
||||
*
|
||||
* @param[in] idx
|
||||
* @param[in] cb_type
|
||||
|
@ -135,11 +140,48 @@ enum
|
|||
* @param[in] data
|
||||
*
|
||||
* @see elm_gesture_layer_cb_set
|
||||
* @see elm_gesture_layer_cb_add
|
||||
*
|
||||
* @ingroup Elm_Gesture_Layer
|
||||
*/
|
||||
#define elm_obj_gesture_layer_cb_set(idx, cb_type, cb, data) ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_CB_SET), EO_TYPECHECK(Elm_Gesture_Type, idx), EO_TYPECHECK(Elm_Gesture_State, cb_type), EO_TYPECHECK(Elm_Gesture_Event_Cb, cb), EO_TYPECHECK(void *, data)
|
||||
|
||||
/**
|
||||
* @def elm_obj_gesture_layer_cb_add
|
||||
* @since 1.8
|
||||
*
|
||||
* Use function to add a callback to be notified about
|
||||
* change of state of gesture.
|
||||
*
|
||||
* @param[in] idx
|
||||
* @param[in] cb_type
|
||||
* @param[in] cb
|
||||
* @param[in] data
|
||||
*
|
||||
* @see elm_gesture_layer_cb_add
|
||||
*
|
||||
* @ingroup Elm_Gesture_Layer
|
||||
*/
|
||||
#define elm_obj_gesture_layer_cb_add(idx, cb_type, cb, data) ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_CB_ADD), EO_TYPECHECK(Elm_Gesture_Type, idx), EO_TYPECHECK(Elm_Gesture_State, cb_type), EO_TYPECHECK(Elm_Gesture_Event_Cb, cb), EO_TYPECHECK(void *, data)
|
||||
|
||||
/**
|
||||
* @def elm_obj_gesture_layer_cb_del
|
||||
* @since 1.8
|
||||
*
|
||||
* Use function to remove a callback that has been added
|
||||
* to be notified about change of state of gesture.
|
||||
*
|
||||
* @param[in] idx
|
||||
* @param[in] cb_type
|
||||
* @param[in] cb
|
||||
* @param[in] data
|
||||
*
|
||||
* @see elm_gesture_layer_cb_del
|
||||
*
|
||||
* @ingroup Elm_Gesture_Layer
|
||||
*/
|
||||
#define elm_obj_gesture_layer_cb_del(idx, cb_type, cb, data) ELM_OBJ_GESTURE_LAYER_ID(ELM_OBJ_GESTURE_LAYER_SUB_ID_CB_DEL), EO_TYPECHECK(Elm_Gesture_Type, idx), EO_TYPECHECK(Elm_Gesture_State, cb_type), EO_TYPECHECK(Elm_Gesture_Event_Cb, cb), EO_TYPECHECK(void *, data)
|
||||
|
||||
/**
|
||||
* @def elm_obj_gesture_layer_tap_finger_size_set
|
||||
* @since 1.8
|
||||
|
|
|
@ -110,6 +110,43 @@ EAPI Eina_Bool elm_gesture_layer_attach(Evas_Object *obj, Evas_Object *target
|
|||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* Use function to add callbacks to be notified about
|
||||
* change of state of gesture.
|
||||
* When a user registers a callback with this function
|
||||
* this means this gesture has to be tested.
|
||||
*
|
||||
* When ALL callbacks for a gesture are set to NULL
|
||||
* it means user isn't interested in gesture-state
|
||||
* and it will not be tested.
|
||||
*
|
||||
* If a function was already set for this gesture/type/state, it will be
|
||||
* replaced by the new one. For ABI compat, callbacks added by
|
||||
* elm_gesture_layer_cb_add will be removed. It is recommended to
|
||||
* use only one of these functions for a gesture object.
|
||||
*
|
||||
* @param obj gesture-layer.
|
||||
* @param idx The gesture you would like to track its state.
|
||||
* @param cb callback function pointer.
|
||||
* @param cb_type what event this callback tracks: START, MOVE, END, ABORT.
|
||||
* @param data user info to be sent to callback (usually, Smart Data)
|
||||
*
|
||||
*/
|
||||
EAPI void elm_gesture_layer_cb_add(Evas_Object *obj, Elm_Gesture_Type idx, Elm_Gesture_State cb_type, Elm_Gesture_Event_Cb cb, void *data);
|
||||
|
||||
/**
|
||||
* Use this function to remove a callback that has been added
|
||||
* to be notified about change of state of gesture.
|
||||
*
|
||||
* @param obj gesture-layer.
|
||||
* @param idx The gesture you would like to track its state.
|
||||
* @param cb callback function pointer.
|
||||
* @param cb_type what event this callback tracks: START, MOVE, END, ABORT.
|
||||
* @param data user info for the callback (usually, Smart Data)
|
||||
*
|
||||
*/
|
||||
EAPI void elm_gesture_layer_cb_del(Evas_Object *obj, Elm_Gesture_Type idx, Elm_Gesture_State cb_type, Elm_Gesture_Event_Cb cb, void *data);
|
||||
|
||||
/**
|
||||
* @since 1.8
|
||||
* This function sets the gesture layer finger-size for taps
|
||||
|
|
Loading…
Reference in New Issue