jackdanielz pushed a commit to branch master.
commit c5ef1cbf87bfcf7eec26b12a480cc3efb79bdc2e
Author: Daniel Zaoui <[email protected]>
Date: Wed Jun 26 09:35:05 2013 +0300
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.
---
ChangeLog | 5 ++
src/lib/elm_gesture_layer.c | 124 +++++++++++++++++++++++++++++++++----
src/lib/elm_gesture_layer_eo.h | 44 ++++++++++++-
src/lib/elm_gesture_layer_legacy.h | 37 +++++++++++
4 files changed, 197 insertions(+), 13 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 7f43061..29358d8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/src/lib/elm_gesture_layer.c b/src/lib/elm_gesture_layer.c
index 5e6e9fa..dc12184 100644
--- a/src/lib/elm_gesture_layer.c
+++ b/src/lib/elm_gesture_layer.c
@@ -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
- * 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;
@@ -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,16 +3967,59 @@ _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)
{
ELM_GESTURE_LAYER_CHECK(obj);
@@ -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
};
diff --git a/src/lib/elm_gesture_layer_eo.h b/src/lib/elm_gesture_layer_eo.h
index a3b9603..d601451 100644
--- a/src/lib/elm_gesture_layer_eo.h
+++ b/src/lib/elm_gesture_layer_eo.h
@@ -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,12 +140,49 @@ 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
*
diff --git a/src/lib/elm_gesture_layer_legacy.h
b/src/lib/elm_gesture_layer_legacy.h
index be0cd8c..b3005de 100644
--- a/src/lib/elm_gesture_layer_legacy.h
+++ b/src/lib/elm_gesture_layer_legacy.h
@@ -111,6 +111,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
* If not set, this size taken from elm_config.
--
------------------------------------------------------------------------------
This SF.net email is sponsored by Windows:
Build for Windows Store.
http://p.sf.net/sfu/windows-dev2dev