Eo: Move event callback handling to base class.

SVN revision: 70990
This commit is contained in:
Tom Hacohen 2012-05-14 07:35:19 +00:00
parent e392db30e3
commit 3053d67f81
14 changed files with 427 additions and 426 deletions

View File

@ -27,7 +27,7 @@ _a_set(Eo *obj, void *class_data, va_list *list)
pd->protected.protected_x1 = a + 1;
pd->protected.public.public_x2 = a + 2;
eo_event_callback_call(obj, EV_A_CHANGED, &pd->a);
eo_do(obj, eo_event_callback_call(EV_A_CHANGED, &pd->a, NULL));
}
static void

View File

@ -25,7 +25,7 @@ _constructor(Eo *obj, void *class_data EINA_UNUSED)
Eo *simple = eo_add(SIMPLE_CLASS, obj);
eo_composite_object_attach(obj, simple);
eo_event_callback_forwarder_add(simple, EV_A_CHANGED, obj);
eo_do(simple, eo_event_callback_forwarder_add(EV_A_CHANGED, obj));
fail_if(eo_composite_is(obj));
fail_if(!eo_composite_is(simple));

View File

@ -27,7 +27,7 @@ main(int argc, char *argv[])
eo_init();
Eo *obj = eo_add(COMP_CLASS, NULL);
eo_event_callback_add(obj, EV_A_CHANGED, _a_changed_cb, NULL);
eo_do(obj, eo_event_callback_add(EV_A_CHANGED, _a_changed_cb, NULL));
int a;
eo_do(obj, simple_a_set(1));
@ -40,7 +40,7 @@ main(int argc, char *argv[])
Eo *simple;
eo_do(obj, eo_base_data_get("simple-obj", (void **) &simple));
eo_ref(simple);
eo_event_callback_forwarder_del(simple, EV_A_CHANGED, obj);
eo_do(simple, eo_event_callback_forwarder_del(EV_A_CHANGED, obj));
cb_called = EINA_FALSE;
eo_do(obj, simple_a_set(2));

View File

@ -19,7 +19,7 @@ _a_set(Eo *obj, void *class_data, va_list *list)
printf("%s %d\n", eo_class_name_get(MY_CLASS), a);
pd->a = a;
eo_event_callback_call(obj, EV_A_CHANGED, &pd->a);
eo_do(obj, eo_event_callback_call(EV_A_CHANGED, &pd->a, NULL));
}
static void

View File

@ -22,7 +22,7 @@ _constructor(Eo *obj, void *class_data EINA_UNUSED)
Eo *bt = eo_add(ELW_BUTTON_CLASS, obj);
eo_composite_object_attach(obj, bt);
eo_event_callback_forwarder_add(bt, EV_CLICKED, obj);
eo_do(bt, eo_event_callback_forwarder_add(EV_CLICKED, obj));
eo_do(bt, evas_obj_visibility_set(EINA_TRUE));
eo_do(obj, elw_box_pack_end(bt));

View File

@ -44,7 +44,7 @@ _btn_clicked(void *data, Evas_Object *evas_obj, void *event_info)
(void) evas_obj;
(void) event_info;
Eo *obj = data;
eo_event_callback_call(obj, EV_CLICKED, NULL);
eo_do(obj, eo_event_callback_call(EV_CLICKED, NULL, NULL));
}
static void

View File

@ -38,7 +38,7 @@ main(int argc, char *argv[])
evas_obj_color_set(255, 0, 0, 255),
elw_button_text_set("Click"),
evas_obj_visibility_set(EINA_TRUE));
eo_event_callback_add(bt, EV_CLICKED, _btn_clicked_cb, "btn");
eo_do(bt, eo_event_callback_add(EV_CLICKED, _btn_clicked_cb, "btn"));
int r, g, b, a;
eo_do(bt, evas_obj_color_get(&r, &g, &b, &a));
@ -50,7 +50,7 @@ main(int argc, char *argv[])
evas_obj_color_set(0, 0, 255, 255),
elw_button_text_set("Click2"),
evas_obj_visibility_set(EINA_TRUE));
eo_event_callback_add(bx, EV_CLICKED, _btn_clicked_cb, "bxedbtn");
eo_do(bx, eo_event_callback_add(EV_CLICKED, _btn_clicked_cb, "bxedbtn"));
elm_run();

View File

@ -30,37 +30,41 @@ main(int argc, char *argv[])
Simple_Public_Data *pd = eo_data_get(obj, SIMPLE_CLASS);
/* The order of these two is undetermined. */
eo_event_callback_priority_add(obj, EV_A_CHANGED, EO_CALLBACK_PRIORITY_BEFORE, _a_changed_cb, (void *) 2);
eo_event_callback_priority_add(obj, EV_A_CHANGED, EO_CALLBACK_PRIORITY_BEFORE, _a_changed_cb, (void *) 1);
eo_do(obj, eo_event_callback_priority_add(EV_A_CHANGED, EO_CALLBACK_PRIORITY_BEFORE, _a_changed_cb, (void *) 2));
eo_do(obj, eo_event_callback_priority_add(EV_A_CHANGED, EO_CALLBACK_PRIORITY_BEFORE, _a_changed_cb, (void *) 1));
/* This will be called afterwards. */
eo_event_callback_priority_add(obj, EV_A_CHANGED, EO_CALLBACK_PRIORITY_DEFAULT, _a_changed_cb, (void *) 3);
eo_do(obj, eo_event_callback_priority_add(EV_A_CHANGED, EO_CALLBACK_PRIORITY_DEFAULT, _a_changed_cb, (void *) 3));
/* This will never be called because the previous callback returns NULL. */
eo_event_callback_priority_add(obj, EV_A_CHANGED, EO_CALLBACK_PRIORITY_AFTER, _a_changed_cb, (void *) 4);
eo_do(obj, eo_event_callback_priority_add(EV_A_CHANGED, EO_CALLBACK_PRIORITY_AFTER, _a_changed_cb, (void *) 4));
eo_do(obj, simple_a_set(1));
fail_if(cb_count != 3);
eo_event_callback_del(obj, EV_A_CHANGED, _a_changed_cb, (void *) 3);
eo_do(obj, eo_event_callback_del(EV_A_CHANGED, _a_changed_cb, (void *) 3));
fail_if(pd->cb_count != 3);
fail_if(eo_event_callback_del(obj, EV_A_CHANGED, _a_changed_cb, (void *) 12));
eo_do(obj, eo_event_callback_del(EV_A_CHANGED, _a_changed_cb, (void *) 12));
fail_if(pd->cb_count != 3);
fail_if(4 != (int) eo_event_callback_del(obj, EV_A_CHANGED, _a_changed_cb, (void *) 4));
eo_do(obj, eo_event_callback_del(EV_A_CHANGED, _a_changed_cb, (void *) 4));
fail_if(pd->cb_count != 2);
eo_event_callback_del_lazy(obj, EV_A_CHANGED, _a_changed_cb);
void *ret;
eo_do(obj, eo_event_callback_del_lazy(EV_A_CHANGED, _a_changed_cb, &ret));
fail_if(pd->cb_count != 1);
fail_if(eo_event_callback_del_lazy(obj, EV_A_CHANGED, NULL));
eo_do(obj, eo_event_callback_del_lazy(EV_A_CHANGED, NULL, &ret));
fail_if(ret);
fail_if(pd->cb_count != 1);
fail_if(eo_event_callback_del(obj, EV_A_CHANGED, NULL, 0));
eo_do(obj, eo_event_callback_del(EV_A_CHANGED, NULL, 0));
fail_if(pd->cb_count != 1);
eo_event_callback_del_lazy(obj, EV_A_CHANGED, _a_changed_cb);
eo_do(obj, eo_event_callback_del_lazy(EV_A_CHANGED, _a_changed_cb, &ret));
fail_if(pd->cb_count != 0);
fail_if(eo_event_callback_del_lazy(obj, EV_A_CHANGED, _a_changed_cb));
eo_do(obj, eo_event_callback_del_lazy(EV_A_CHANGED, _a_changed_cb, &ret));
fail_if(ret);
fail_if(pd->cb_count != 0);
eo_unref(obj);

View File

@ -25,7 +25,7 @@ _a_set(Eo *obj, void *class_data, va_list *list)
pd->a = a;
printf("%s %d\n", __func__, pd->a);
eo_event_callback_call(obj, EV_A_CHANGED, &pd->a);
eo_do(obj, eo_event_callback_call(EV_A_CHANGED, &pd->a, NULL));
}
Eina_Bool
@ -67,8 +67,8 @@ _constructor(Eo *obj, void *class_data EINA_UNUSED)
{
eo_constructor_super(obj);
eo_event_callback_add(obj, EO_EV_CALLBACK_ADD, _cb_added, NULL);
eo_event_callback_add(obj, EO_EV_CALLBACK_DEL, _cb_deled, NULL);
eo_do(obj, eo_event_callback_add(EO_EV_CALLBACK_ADD, _cb_added, NULL));
eo_do(obj, eo_event_callback_add(EO_EV_CALLBACK_DEL, _cb_deled, NULL));
eo_do(obj, eo_base_data_set("cb_count", (intptr_t) 0, NULL));
}

View File

@ -555,7 +555,7 @@ EAPI void *eo_data_get(const Eo *obj, const Eo_Class *klass);
* @see eo_unref()
* @see eo_ref_get()
*/
EAPI Eo *eo_ref(Eo *obj);
EAPI Eo *eo_ref(const Eo *obj);
/**
* @brief Decrement the object's reference count by 1 and free it if needed.
@ -564,7 +564,7 @@ EAPI Eo *eo_ref(Eo *obj);
* @see eo_ref()
* @see eo_ref_get()
*/
EAPI void eo_unref(Eo *obj);
EAPI void eo_unref(const Eo *obj);
/**
* @brief Return the ref count of the object passed.
@ -655,156 +655,6 @@ EAPI void eo_composite_object_detach(Eo *obj, Eo *comp_obj);
*/
EAPI Eina_Bool eo_composite_is(Eo *comp_obj);
/**
* @}
*/
/**
* @addtogroup Eo_Events Eo's Event Handling
* @{
*/
/**
* @def EO_CALLBACK_PRIORITY_BEFORE
* Slightly more prioritized than default.
*/
#define EO_CALLBACK_PRIORITY_BEFORE -100
/**
* @def EO_CALLBACK_PRIORITY_DEFAULT
* Default callback priority level
*/
#define EO_CALLBACK_PRIORITY_DEFAULT 0
/**
* @def EO_CALLBACK_PRIORITY_AFTER
* Slightly less prioritized than default.
*/
#define EO_CALLBACK_PRIORITY_AFTER 100
/**
* @typedef Eo_Callback_Priority
*
* Callback priority value. Range is -32k - 32k. The lower the number, the
* higher the priority.
*
* @see EO_CALLBACK_PRIORITY_AFTER
* @see EO_CALLBACK_PRIORITY_BEFORE
* @see EO_CALLBACK_PRIORITY_DEFAULT
*/
typedef short Eo_Callback_Priority;
/**
* @def EO_CALLBACK_STOP
* Stop calling callbacks for the even of which the callback was called for.
* @see EO_CALLBACK_CONTINUE
*/
#define EO_CALLBACK_STOP EINA_FALSE
/**
* @def EO_CALLBACK_CONTINUE
* Continue calling callbacks for the even of which the callback was called for.
* @see EO_CALLBACK_STOP
*/
#define EO_CALLBACK_CONTINUE EINA_TRUE
/**
* @typedef Eo_Event_Cb
*
* An event callback prototype.
*
* @param data The user data registered with the callback.
* @param obj The object which initiated the event.
* @param desc The event's description.
* @param event_info additional data passed with the event.
* @return #EO_CALLBACK_STOP to stop calling additional callbacks for the event, #EO_CALLBACK_CONTINUE to continue.
*/
typedef Eina_Bool (*Eo_Event_Cb)(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info);
/**
* @brief Add an event callback forwarder for an event and an object.
* @param obj The object to listen to events on.
* @param desc The description of the event to listen to.
* @param new_obj The object to emit events from.
* @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
*
* @see eo_event_callback_forwarder_del()
*/
EAPI Eina_Bool eo_event_callback_forwarder_add(Eo *obj, const Eo_Event_Description *desc, Eo *new_obj);
/**
* @brief Remove an event callback forwarder for an event and an object.
* @param obj The object to listen to events on.
* @param desc The description of the event to listen to.
* @param new_obj The object to emit events from.
* @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
*
* @see eo_event_callback_forwarder_add()
*/
EAPI Eina_Bool eo_event_callback_forwarder_del(Eo *obj, const Eo_Event_Description *desc, Eo *new_obj);
/**
* @def eo_event_callback_add(obj, desc, cb, data)
* Add a callback for an event.
* @param obj The object to listen to events on.
* @param desc The description of the event to listen to.
* @param cb the callback to call.
* @param data additional data to pass to the callback.
* @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
*
* callbacks of the same priority are called in reverse order of creation.
*
* @see eo_event_callback_priority_add()
*/
#define eo_event_callback_add(obj, desc, cb, data) \
eo_event_callback_priority_add(obj, desc, \
EO_CALLBACK_PRIORITY_DEFAULT, cb, data)
/**
* @brief Add a callback for an event with a specific priority.
* @param obj The object to listen to events on.
* @param desc The description of the event to listen to.
* @param priority The priority of the callback.
* @param cb the callback to call.
* @param data additional data to pass to the callback.
* @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
*
* callbacks of the same priority are called in reverse order of creation.
*
* @see #eo_event_callback_add
*/
EAPI Eina_Bool eo_event_callback_priority_add(Eo *obj, const Eo_Event_Description *desc, Eo_Callback_Priority priority, Eo_Event_Cb cb, const void *data);
/**
* @brief Del a callback for an event
* @param obj The object to listen to delete from.
* @param desc The description of the event to listen to.
* @param func the callback to delete.
* @return The additional data that was set to be passed to the callback.
*
* @see eo_event_callback_del()
*/
EAPI void *eo_event_callback_del_lazy(Eo *obj, const Eo_Event_Description *desc, Eo_Event_Cb func);
/**
* @brief Del a callback with a specific data associated to it for an event.
* @param obj The object to listen to delete from.
* @param desc The description of the event to listen to.
* @param func the callback to delete.
* @param user_data The data to compare.
* @return The additional data that was set to be passed to the callback.
*
* @see eo_event_callback_del_lazy()
*/
EAPI void *eo_event_callback_del(Eo *obj, const Eo_Event_Description *desc, Eo_Event_Cb func, const void *user_data);
/**
* @brief Call the callbacks for an event of an object.
* @param obj The object to work on.
* @param desc The description of the event to call.
* @param event_info Extra event info to pass to the callbacks.
* @return @c EINA_FALSE if one of the callbacks aborted the callback calls or @c EINA_TRUE otherwise.
*/
EAPI Eina_Bool eo_event_callback_call(Eo *obj, const Eo_Event_Description *desc, const void *event_info);
/**
* @}
*/
@ -843,6 +693,12 @@ enum {
EO_BASE_SUB_ID_DATA_DEL,
EO_BASE_SUB_ID_WREF_ADD,
EO_BASE_SUB_ID_WREF_DEL,
EO_BASE_SUB_ID_EVENT_CALLBACK_PRIORITY_ADD,
EO_BASE_SUB_ID_EVENT_CALLBACK_DEL,
EO_BASE_SUB_ID_EVENT_CALLBACK_DEL_LAZY,
EO_BASE_SUB_ID_EVENT_CALLBACK_CALL,
EO_BASE_SUB_ID_EVENT_CALLBACK_FORWARDER_ADD,
EO_BASE_SUB_ID_EVENT_CALLBACK_FORWARDER_DEL,
EO_BASE_SUB_ID_LAST
};
@ -924,6 +780,145 @@ enum {
if (*wref) eo_do(*wref, eo_wref_del(wref)); \
} while (0)
/**
* @addtogroup Eo_Events Eo's Event Handling
* @{
*/
/**
* @def EO_CALLBACK_PRIORITY_BEFORE
* Slightly more prioritized than default.
*/
#define EO_CALLBACK_PRIORITY_BEFORE -100
/**
* @def EO_CALLBACK_PRIORITY_DEFAULT
* Default callback priority level
*/
#define EO_CALLBACK_PRIORITY_DEFAULT 0
/**
* @def EO_CALLBACK_PRIORITY_AFTER
* Slightly less prioritized than default.
*/
#define EO_CALLBACK_PRIORITY_AFTER 100
/**
* @typedef Eo_Callback_Priority
*
* Callback priority value. Range is -32k - 32k. The lower the number, the
* higher the priority.
*
* @see EO_CALLBACK_PRIORITY_AFTER
* @see EO_CALLBACK_PRIORITY_BEFORE
* @see EO_CALLBACK_PRIORITY_DEFAULT
*/
typedef short Eo_Callback_Priority;
/**
* @def EO_CALLBACK_STOP
* Stop calling callbacks for the even of which the callback was called for.
* @see EO_CALLBACK_CONTINUE
*/
#define EO_CALLBACK_STOP EINA_FALSE
/**
* @def EO_CALLBACK_CONTINUE
* Continue calling callbacks for the even of which the callback was called for.
* @see EO_CALLBACK_STOP
*/
#define EO_CALLBACK_CONTINUE EINA_TRUE
/**
* @typedef Eo_Event_Cb
*
* An event callback prototype.
*
* @param data The user data registered with the callback.
* @param obj The object which initiated the event.
* @param desc The event's description.
* @param event_info additional data passed with the event.
* @return #EO_CALLBACK_STOP to stop calling additional callbacks for the event, #EO_CALLBACK_CONTINUE to continue.
*/
typedef Eina_Bool (*Eo_Event_Cb)(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info);
/**
* @brief Add an event callback forwarder for an event and an object.
* @param desc[in] The description of the event to listen to.
* @param new_obj[in] The object to emit events from.
*
* @see eo_event_callback_forwarder_del()
*/
#define eo_event_callback_forwarder_add(desc, new_obj) EO_BASE_ID(EO_BASE_SUB_ID_EVENT_CALLBACK_FORWARDER_ADD), EO_TYPECHECK(const Eo_Event_Description *, desc), EO_TYPECHECK(Eo *, new_obj)
/**
* @brief Remove an event callback forwarder for an event and an object.
* @param desc[in] The description of the event to listen to.
* @param new_obj[in] The object to emit events from.
*
* @see eo_event_callback_forwarder_add()
*/
#define eo_event_callback_forwarder_del(desc, new_obj) EO_BASE_ID(EO_BASE_SUB_ID_EVENT_CALLBACK_FORWARDER_DEL), EO_TYPECHECK(const Eo_Event_Description *, desc), EO_TYPECHECK(Eo *, new_obj)
/**
* @def eo_event_callback_add(obj, desc, cb, data)
* Add a callback for an event.
* @param desc[in] The description of the event to listen to.
* @param cb[in] the callback to call.
* @param data[in] additional data to pass to the callback.
*
* callbacks of the same priority are called in reverse order of creation.
*
* @see eo_event_callback_priority_add()
*/
#define eo_event_callback_add(desc, cb, data) \
eo_event_callback_priority_add(desc, \
EO_CALLBACK_PRIORITY_DEFAULT, cb, data)
/**
* @brief Add a callback for an event with a specific priority.
* @param desc[in] The description of the event to listen to.
* @param priority[in] The priority of the callback.
* @param cb[in] the callback to call.
* @param data[in] additional data to pass to the callback.
*
* callbacks of the same priority are called in reverse order of creation.
*
* @see #eo_event_callback_add
*/
#define eo_event_callback_priority_add(desc, priority, cb, data) EO_BASE_ID(EO_BASE_SUB_ID_EVENT_CALLBACK_PRIORITY_ADD), EO_TYPECHECK(const Eo_Event_Description *, desc), EO_TYPECHECK(Eo_Callback_Priority, priority), EO_TYPECHECK(Eo_Event_Cb, cb), EO_TYPECHECK(const void *, data)
/**
* @brief Del a callback for an event
* @param desc[in] The description of the event to listen to.
* @param func[in] the callback to delete.
* @param user_data[out] The user data associated with the callback func.
*
* @see eo_event_callback_del()
*/
#define eo_event_callback_del_lazy(desc, func, user_data) EO_BASE_ID(EO_BASE_SUB_ID_EVENT_CALLBACK_DEL_LAZY), EO_TYPECHECK(const Eo_Event_Description *, desc), EO_TYPECHECK(Eo_Event_Cb, func), EO_TYPECHECK(void **, user_data)
/**
* @brief Del a callback with a specific data associated to it for an event.
* @param desc[in] The description of the event to listen to.
* @param func[in] the callback to delete.
* @param user_data[in] The data to compare.
*
* @see eo_event_callback_del_lazy()
*/
#define eo_event_callback_del(desc, func, user_data) EO_BASE_ID(EO_BASE_SUB_ID_EVENT_CALLBACK_DEL), EO_TYPECHECK(const Eo_Event_Description *, desc), EO_TYPECHECK(Eo_Event_Cb, func), EO_TYPECHECK(const void *, user_data)
/**
* @brief Call the callbacks for an event of an object.
* @param desc[in] The description of the event to call.
* @param event_info[in] Extra event info to pass to the callbacks.
* @param aborted[out] @c EINA_TRUE if one of the callbacks aborted the call, @c EINA_FALSE otherwise.
*/
#define eo_event_callback_call(desc, event_info, aborted) EO_BASE_ID(EO_BASE_SUB_ID_EVENT_CALLBACK_CALL), EO_TYPECHECK(const Eo_Event_Description *, desc), EO_TYPECHECK(const void *, event_info), EO_TYPECHECK(Eina_Bool *, aborted)
/**
* @}
*/
/**
* @var _EO_EV_CALLBACK_ADD
* see EO_EV_CALLBACK_ADD

View File

@ -15,7 +15,6 @@ static Eo_Class **_eo_classes;
static Eo_Class_Id _eo_classes_last_id;
static Eina_Bool _eo_init_count = 0;
static void _eo_callback_remove_all(Eo *obj);
static void _eo_constructor(Eo *obj, const Eo_Class *klass);
static void _eo_destructor(Eo *obj, const Eo_Class *klass);
static void eo_constructor_error_unset(Eo *obj);
@ -23,39 +22,12 @@ static inline void *_eo_data_get(const Eo *obj, const Eo_Class *klass);
static inline Eo *_eo_ref(Eo *obj);
static inline void _eo_unref(Eo *obj);
typedef struct _Eo_Callback_Description Eo_Callback_Description;
typedef struct
{
Eo_Op op;
const Eo_Class **kls_itr;
} Eo_Kls_Itr;
#define EO_EINA_MAGIC 0xa186bc32 /* Nothing magical about this number. */
#define EO_EINA_MAGIC_STR "Eo"
#define EO_DELETED_EINA_MAGIC 0xa186bb32 /* Nothing magical about this number. */
#define EO_DELETED_EINA_MAGIC_STR "Eo - Deleted object"
#define EO_CLASS_EINA_MAGIC 0xa186ba32 /* Nothing magical about this number. */
#define EO_CLASS_EINA_MAGIC_STR "Eo Class"
#define EO_MAGIC_RETURN_VAL(d, magic, ret) \
do { \
if (!EINA_MAGIC_CHECK(d, magic)) \
{ \
EINA_MAGIC_FAIL(d, magic); \
return ret; \
} \
} while (0)
#define EO_MAGIC_RETURN(d, magic) \
do { \
if (!EINA_MAGIC_CHECK(d, magic)) \
{ \
EINA_MAGIC_FAIL(d, magic); \
return; \
} \
} while (0)
struct _Eo {
EINA_MAGIC
Eo *parent;
@ -67,9 +39,6 @@ struct _Eo {
Eina_List *composite_objects;
Eina_Inlist *callbacks;
int walking_list;
Eo_Kls_Itr mro_itr;
Eina_Bool del:1;
@ -1058,8 +1027,9 @@ _eo_ref(Eo *obj)
}
EAPI Eo *
eo_ref(Eo *obj)
eo_ref(const Eo *_obj)
{
Eo *obj = (Eo *) _obj;
EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, obj);
return _eo_ref(obj);
@ -1073,7 +1043,7 @@ _eo_del_internal(Eo *obj)
/* We need that for the event callbacks that may ref/unref. */
obj->refcount++;
eo_event_callback_call(obj, EO_EV_DEL, NULL);
eo_do(obj, eo_event_callback_call(EO_EV_DEL, NULL, NULL));
obj->del = EINA_TRUE;
const Eo_Class *klass = eo_class_get(obj);
@ -1122,16 +1092,15 @@ _eo_unref(Eo *obj)
}
#endif
_eo_callback_remove_all(obj);
EINA_MAGIC_SET(obj, EO_DELETED_EINA_MAGIC);
free(obj);
}
}
EAPI void
eo_unref(Eo *obj)
eo_unref(const Eo *_obj)
{
Eo *obj = (Eo *) _obj;
EO_MAGIC_RETURN(obj, EO_EINA_MAGIC);
_eo_unref(obj);
@ -1396,207 +1365,4 @@ eo_composite_is(Eo *emb_obj)
return EINA_FALSE;
}
/* Callbacks */
struct _Eo_Callback_Description
{
EINA_INLIST;
const Eo_Event_Description *event;
Eo_Event_Cb func;
void *func_data;
Eo_Callback_Priority priority;
Eina_Bool delete_me : 1;
};
/* Actually remove, doesn't care about walking list, or delete_me */
static void
_eo_callback_remove(Eo *obj, Eo_Callback_Description *cb)
{
obj->callbacks = eina_inlist_remove(obj->callbacks,
EINA_INLIST_GET(cb));
free(cb);
}
/* Actually remove, doesn't care about walking list, or delete_me */
static void
_eo_callback_remove_all(Eo *obj)
{
Eina_Inlist *initr;
Eo_Callback_Description *cb = NULL;
EINA_INLIST_FOREACH_SAFE(obj->callbacks, initr, cb)
{
_eo_callback_remove(obj, cb);
}
}
static void
_eo_callbacks_clear(Eo *obj)
{
Eina_Inlist *itn;
Eo_Callback_Description *cb = NULL;
/* Abort if we are currently walking the list. */
if (obj->walking_list > 0)
return;
EINA_INLIST_FOREACH_SAFE(obj->callbacks, itn, cb)
{
if (cb->delete_me)
{
_eo_callback_remove(obj, cb);
}
}
}
static int
_callback_priority_cmp(const void *_a, const void *_b)
{
const Eo_Callback_Description *a, *b;
a = (const Eo_Callback_Description *) _a;
b = (const Eo_Callback_Description *) _b;
if (a->priority < b->priority)
return -1;
else
return 1;
}
EAPI Eina_Bool
eo_event_callback_priority_add(Eo *obj,
const Eo_Event_Description *desc,
Eo_Callback_Priority priority,
Eo_Event_Cb func,
const void *data)
{
EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, EINA_FALSE);
Eo_Callback_Description *cb = calloc(1, sizeof(*cb));
cb->event = desc;
cb->func = func;
cb->func_data = (void *) data;
cb->priority = priority;
obj->callbacks = eina_inlist_sorted_insert(obj->callbacks,
EINA_INLIST_GET(cb), _callback_priority_cmp);
eo_event_callback_call(obj, EO_EV_CALLBACK_ADD, desc);
return EINA_TRUE;
}
EAPI void *
eo_event_callback_del_lazy(Eo *obj, const Eo_Event_Description *desc, Eo_Event_Cb func)
{
EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, NULL);
void *ret = NULL;
Eo_Callback_Description *cb;
EINA_INLIST_FOREACH(obj->callbacks, cb)
{
if ((cb->event == desc) && (cb->func == func))
{
void *data;
data = cb->func_data;
cb->delete_me = EINA_TRUE;
_eo_callbacks_clear(obj);
ret = data;
goto found;
}
}
return NULL;
found:
eo_event_callback_call(obj, EO_EV_CALLBACK_DEL, desc);
return ret;
}
EAPI void *
eo_event_callback_del(Eo *obj, const Eo_Event_Description *desc, Eo_Event_Cb func, const void *user_data)
{
EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, NULL);
void *ret = NULL;
Eo_Callback_Description *cb;
EINA_INLIST_FOREACH(obj->callbacks, cb)
{
if ((cb->event == desc) && (cb->func == func) &&
(cb->func_data == user_data))
{
void *data;
data = cb->func_data;
cb->delete_me = EINA_TRUE;
_eo_callbacks_clear(obj);
ret = data;
goto found;
}
}
return NULL;
found:
eo_event_callback_call(obj, EO_EV_CALLBACK_DEL, desc);
return ret;
}
EAPI Eina_Bool
eo_event_callback_call(Eo *obj, const Eo_Event_Description *desc,
const void *event_info)
{
EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, EINA_FALSE);
Eina_Bool ret = EINA_TRUE;
Eo_Callback_Description *cb;
_eo_ref(obj);
obj->walking_list++;
EINA_INLIST_FOREACH(obj->callbacks, cb)
{
if (!cb->delete_me && (cb->event == desc))
{
/* Abort callback calling if the func says so. */
if (!cb->func((void *) cb->func_data, obj, desc,
(void *) event_info))
{
ret = EINA_FALSE;
break;
}
}
if (obj->del)
break;
}
obj->walking_list--;
_eo_callbacks_clear(obj);
_eo_unref(obj);
return ret;
}
static Eina_Bool
_eo_event_forwarder_callback(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info)
{
(void) obj;
Eo *new_obj = (Eo *) data;
return eo_event_callback_call(new_obj, desc, event_info);
}
/* FIXME: Change default priority? Maybe call later? */
EAPI Eina_Bool
eo_event_callback_forwarder_add(Eo *obj, const Eo_Event_Description *desc, Eo *new_obj)
{
EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, EINA_FALSE);
EO_MAGIC_RETURN_VAL(new_obj, EO_EINA_MAGIC, EINA_FALSE);
return eo_event_callback_add(obj, desc, _eo_event_forwarder_callback, new_obj);
}
EAPI Eina_Bool
eo_event_callback_forwarder_del(Eo *obj, const Eo_Event_Description *desc, Eo *new_obj)
{
EO_MAGIC_RETURN_VAL(obj, EO_EINA_MAGIC, EINA_FALSE);
EO_MAGIC_RETURN_VAL(new_obj, EO_EINA_MAGIC, EINA_FALSE);
eo_event_callback_del(obj, desc, _eo_event_forwarder_callback, new_obj);
return EINA_TRUE;
}

View File

@ -11,6 +11,9 @@ typedef struct
{
Eina_Inlist *generic_data;
Eo ***wrefs;
Eina_Inlist *callbacks;
int walking_list;
} Private_Data;
typedef struct
@ -222,6 +225,209 @@ _wref_destruct(Private_Data *pd)
/* EOF Weak reference. */
/* Event callbacks */
/* Callbacks */
typedef struct
{
EINA_INLIST;
const Eo_Event_Description *event;
Eo_Event_Cb func;
void *func_data;
Eo_Callback_Priority priority;
Eina_Bool delete_me : 1;
} Eo_Callback_Description;
/* Actually remove, doesn't care about walking list, or delete_me */
static void
_eo_callback_remove(Private_Data *pd, Eo_Callback_Description *cb)
{
pd->callbacks = eina_inlist_remove(pd->callbacks,
EINA_INLIST_GET(cb));
free(cb);
}
/* Actually remove, doesn't care about walking list, or delete_me */
static void
_eo_callback_remove_all(Private_Data *pd)
{
Eina_Inlist *initr;
Eo_Callback_Description *cb = NULL;
EINA_INLIST_FOREACH_SAFE(pd->callbacks, initr, cb)
{
_eo_callback_remove(pd, cb);
}
}
static void
_eo_callbacks_clear(Private_Data *pd)
{
Eina_Inlist *itn;
Eo_Callback_Description *cb = NULL;
/* Abort if we are currently walking the list. */
if (pd->walking_list > 0)
return;
EINA_INLIST_FOREACH_SAFE(pd->callbacks, itn, cb)
{
if (cb->delete_me)
{
_eo_callback_remove(pd, cb);
}
}
}
static int
_callback_priority_cmp(const void *_a, const void *_b)
{
const Eo_Callback_Description *a, *b;
a = (const Eo_Callback_Description *) _a;
b = (const Eo_Callback_Description *) _b;
if (a->priority < b->priority)
return -1;
else
return 1;
}
static void
_ev_cb_priority_add(Eo *obj, void *class_data, va_list *list)
{
Private_Data *pd = (Private_Data *) class_data;
const Eo_Event_Description *desc = va_arg(*list, const Eo_Event_Description *);
Eo_Callback_Priority priority = va_arg(*list, int);
Eo_Event_Cb func = va_arg(*list, Eo_Event_Cb);
const void *data = va_arg(*list, const void *);
Eo_Callback_Description *cb = calloc(1, sizeof(*cb));
cb->event = desc;
cb->func = func;
cb->func_data = (void *) data;
cb->priority = priority;
pd->callbacks = eina_inlist_sorted_insert(pd->callbacks,
EINA_INLIST_GET(cb), _callback_priority_cmp);
eo_do(obj, eo_event_callback_call(EO_EV_CALLBACK_ADD, desc, NULL));
}
static void
_ev_cb_del_lazy(Eo *obj, void *class_data, va_list *list)
{
Private_Data *pd = (Private_Data *) class_data;
const Eo_Event_Description *desc = va_arg(*list, const Eo_Event_Description *);
Eo_Event_Cb func = va_arg(*list, Eo_Event_Cb);
void **ret = va_arg(*list, void **);
Eo_Callback_Description *cb;
EINA_INLIST_FOREACH(pd->callbacks, cb)
{
if ((cb->event == desc) && (cb->func == func))
{
void *data;
data = cb->func_data;
cb->delete_me = EINA_TRUE;
_eo_callbacks_clear(pd);
if (ret) *ret = data;
eo_do(obj, eo_event_callback_call(EO_EV_CALLBACK_DEL, desc, NULL));
return;
}
}
if (ret) *ret = NULL;
}
static void
_ev_cb_del(Eo *obj, void *class_data, va_list *list)
{
Private_Data *pd = (Private_Data *) class_data;
const Eo_Event_Description *desc = va_arg(*list, const Eo_Event_Description *);
Eo_Event_Cb func = va_arg(*list, Eo_Event_Cb);
void *user_data = va_arg(*list, void *);
Eo_Callback_Description *cb;
EINA_INLIST_FOREACH(pd->callbacks, cb)
{
if ((cb->event == desc) && (cb->func == func) &&
(cb->func_data == user_data))
{
cb->delete_me = EINA_TRUE;
_eo_callbacks_clear(pd);
eo_do(obj, eo_event_callback_call(EO_EV_CALLBACK_DEL, desc, NULL));
return;
}
}
}
static void
_ev_cb_call(const Eo *_obj, const void *class_data, va_list *list)
{
Private_Data *pd = (Private_Data *) class_data;
Eo *obj = (Eo *) _obj;
const Eo_Event_Description *desc = va_arg(*list, const Eo_Event_Description *);
void *event_info = va_arg(*list, void *);
Eina_Bool *ret = va_arg(*list, Eina_Bool *);
Eo_Callback_Description *cb;
if (ret) *ret = EINA_TRUE;
/* FIXME: Change eo_ref to _eo_ref and unref. */
eo_ref(obj);
pd->walking_list++;
EINA_INLIST_FOREACH(pd->callbacks, cb)
{
if (!cb->delete_me && (cb->event == desc))
{
/* Abort callback calling if the func says so. */
if (!cb->func((void *) cb->func_data, obj, desc,
(void *) event_info))
{
if (ret) *ret = EINA_FALSE;
break;
}
}
}
pd->walking_list--;
_eo_callbacks_clear(pd);
eo_unref(obj);
}
static Eina_Bool
_eo_event_forwarder_callback(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info)
{
(void) obj;
Eo *new_obj = (Eo *) data;
Eina_Bool ret;
eo_do(new_obj, eo_event_callback_call(desc, event_info, &ret));
return ret;
}
/* FIXME: Change default priority? Maybe call later? */
static void
_ev_cb_forwarder_add(Eo *obj, void *class_data EINA_UNUSED, va_list *list)
{
const Eo_Event_Description *desc = va_arg(*list, const Eo_Event_Description *);
Eo *new_obj = va_arg(*list, Eo *);
/* FIXME: Add it EO_MAGIC_RETURN(new_obj, EO_EINA_MAGIC); */
eo_do(obj, eo_event_callback_add(desc, _eo_event_forwarder_callback, new_obj));
}
static void
_ev_cb_forwarder_del(Eo *obj, void *class_data EINA_UNUSED, va_list *list)
{
const Eo_Event_Description *desc = va_arg(*list, const Eo_Event_Description *);
Eo *new_obj = va_arg(*list, Eo *);
/* FIXME: Add it EO_MAGIC_RETURN(new_obj, EO_EINA_MAGIC); */
eo_do(obj, eo_event_callback_del(desc, _eo_event_forwarder_callback, new_obj));
}
/* EOF event callbacks */
/* EO_BASE_CLASS stuff */
#define MY_CLASS EO_BASE_CLASS
@ -247,6 +453,7 @@ _destructor(Eo *obj, void *class_data)
_eo_generic_data_del_all(class_data);
_wref_destruct(class_data);
_eo_callback_remove_all(class_data);
}
static void
@ -258,6 +465,12 @@ _class_constructor(Eo_Class *klass)
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DATA_DEL), _data_del),
EO_OP_FUNC_CONST(EO_BASE_ID(EO_BASE_SUB_ID_WREF_ADD), _wref_add),
EO_OP_FUNC_CONST(EO_BASE_ID(EO_BASE_SUB_ID_WREF_DEL), _wref_del),
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_EVENT_CALLBACK_PRIORITY_ADD), _ev_cb_priority_add),
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_EVENT_CALLBACK_DEL), _ev_cb_del),
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_EVENT_CALLBACK_DEL_LAZY), _ev_cb_del_lazy),
EO_OP_FUNC_CONST(EO_BASE_ID(EO_BASE_SUB_ID_EVENT_CALLBACK_CALL), _ev_cb_call),
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_EVENT_CALLBACK_FORWARDER_ADD), _ev_cb_forwarder_add),
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_EVENT_CALLBACK_FORWARDER_DEL), _ev_cb_forwarder_del),
EO_OP_FUNC_SENTINEL
};
@ -270,12 +483,16 @@ static const Eo_Op_Description op_desc[] = {
EO_OP_DESCRIPTION(EO_BASE_SUB_ID_DATA_DEL, "?", "Del key."),
EO_OP_DESCRIPTION_CONST(EO_BASE_SUB_ID_WREF_ADD, "?", "Add a weak ref to the object."),
EO_OP_DESCRIPTION_CONST(EO_BASE_SUB_ID_WREF_DEL, "?", "Delete the weak ref."),
EO_OP_DESCRIPTION(EO_BASE_SUB_ID_EVENT_CALLBACK_PRIORITY_ADD, "?", "Add an event callback with a priority."),
EO_OP_DESCRIPTION(EO_BASE_SUB_ID_EVENT_CALLBACK_DEL, "?", "Delete an event callback"),
EO_OP_DESCRIPTION(EO_BASE_SUB_ID_EVENT_CALLBACK_DEL_LAZY, "?", "Delete an event callback in a lazy way."),
EO_OP_DESCRIPTION_CONST(EO_BASE_SUB_ID_EVENT_CALLBACK_CALL, "?", "Call the event callbacks for an event."),
EO_OP_DESCRIPTION(EO_BASE_SUB_ID_EVENT_CALLBACK_FORWARDER_ADD, "?", "Add an event forwarder."),
EO_OP_DESCRIPTION(EO_BASE_SUB_ID_EVENT_CALLBACK_FORWARDER_DEL, "?", "Delete an event forwarder."),
EO_OP_DESCRIPTION_SENTINEL
};
static const Eo_Event_Description *event_desc[] = {
EO_EV_CALLBACK_ADD,
EO_EV_CALLBACK_DEL,
EO_EV_DEL,
NULL
};

View File

@ -1,6 +1,32 @@
#ifndef _EO_PRIVATE_H
#define _EO_PRIVATE_H
#define EO_EINA_MAGIC 0xa186bc32 /* Nothing magical about this number. */
#define EO_EINA_MAGIC_STR "Eo"
#define EO_DELETED_EINA_MAGIC 0xa186bb32 /* Nothing magical about this number. */
#define EO_DELETED_EINA_MAGIC_STR "Eo - Deleted object"
#define EO_CLASS_EINA_MAGIC 0xa186ba32 /* Nothing magical about this number. */
#define EO_CLASS_EINA_MAGIC_STR "Eo Class"
#define EO_MAGIC_RETURN_VAL(d, magic, ret) \
do { \
if (!EINA_MAGIC_CHECK(d, magic)) \
{ \
EINA_MAGIC_FAIL(d, magic); \
return ret; \
} \
} while (0)
#define EO_MAGIC_RETURN(d, magic) \
do { \
if (!EINA_MAGIC_CHECK(d, magic)) \
{ \
EINA_MAGIC_FAIL(d, magic); \
return; \
} \
} while (0)
extern int _eo_log_dom;
#ifdef CRITICAL

View File

@ -369,15 +369,8 @@ START_TEST(eo_magic_checks)
eo_composite_object_detach(obj, (Eo *) buf);
eo_composite_is((Eo *) buf);
fail_if(eo_event_callback_add((Eo *) buf, NULL, NULL, NULL));
fail_if(eo_event_callback_del_lazy((Eo *) buf, NULL, NULL));
fail_if(eo_event_callback_del((Eo *) buf, NULL, NULL, NULL));
fail_if(eo_event_callback_call((Eo *) buf, NULL, NULL));
fail_if(eo_event_callback_forwarder_add((Eo *) buf, NULL, obj));
fail_if(eo_event_callback_forwarder_add(obj, NULL, (Eo *) buf));
fail_if(eo_event_callback_forwarder_del((Eo *) buf, NULL, obj));
fail_if(eo_event_callback_forwarder_del(obj, NULL, (Eo *) buf));
eo_do(obj, eo_event_callback_forwarder_add(NULL, (Eo *) buf));
eo_do(obj, eo_event_callback_forwarder_del(NULL, (Eo *) buf));
eo_unref(obj);