From 7041c968bfc0b8ced49a26227286aae2adb073ef Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Tue, 4 May 2010 15:58:10 +0000 Subject: [PATCH] oooh you'd love to know why this is here.. won't you? :) SVN revision: 48613 --- legacy/evas/src/lib/Evas.h | 18 ++- legacy/evas/src/lib/canvas/evas_callbacks.c | 134 ++++++++++++++++++ legacy/evas/src/lib/canvas/evas_events.c | 24 +++- legacy/evas/src/lib/canvas/evas_focus.c | 6 +- legacy/evas/src/lib/canvas/evas_main.c | 2 + .../evas/src/lib/canvas/evas_object_inform.c | 7 + legacy/evas/src/lib/canvas/evas_object_main.c | 4 + legacy/evas/src/lib/include/evas_private.h | 13 ++ 8 files changed, 195 insertions(+), 13 deletions(-) diff --git a/legacy/evas/src/lib/Evas.h b/legacy/evas/src/lib/Evas.h index 5ee2ccfbfb..05900496e9 100644 --- a/legacy/evas/src/lib/Evas.h +++ b/legacy/evas/src/lib/Evas.h @@ -591,9 +591,10 @@ typedef enum _Evas_Object_Pointer_Mode EVAS_OBJECT_POINTER_MODE_NOGRAB } Evas_Object_Pointer_Mode; /**< How mouse pointer should be handled by Evas. */ -typedef void (*Evas_Smart_Cb) (void *data, Evas_Object *obj, void *event_info); -typedef void (*Evas_Event_Cb) (void *data, Evas *e, void *event_info); -typedef void (*Evas_Object_Event_Cb) (void *data, Evas *e, Evas_Object *obj, void *event_info); +typedef void (*Evas_Smart_Cb) (void *data, Evas_Object *obj, void *event_info); +typedef void (*Evas_Event_Cb) (void *data, Evas *e, void *event_info); +typedef Eina_Bool (*Evas_Object_Event_Post_Cb) (void *data, Evas *e); +typedef void (*Evas_Object_Event_Cb) (void *data, Evas *e, Evas_Object *obj, void *event_info); #ifdef __cplusplus extern "C" { @@ -769,10 +770,13 @@ extern "C" { * @ingroup Evas_Canvas */ - EAPI void evas_event_callback_add (Evas *e, Evas_Callback_Type type, Evas_Event_Cb func, const void *data) EINA_ARG_NONNULL(1, 3); - EAPI void *evas_event_callback_del (Evas *e, Evas_Callback_Type type, Evas_Event_Cb func) EINA_ARG_NONNULL(1, 3); - EAPI void *evas_event_callback_del_full (Evas *e, Evas_Callback_Type type, Evas_Event_Cb func, const void *data) EINA_ARG_NONNULL(1, 3); - + EAPI void evas_event_callback_add (Evas *e, Evas_Callback_Type type, Evas_Event_Cb func, const void *data) EINA_ARG_NONNULL(1, 3); + EAPI void *evas_event_callback_del (Evas *e, Evas_Callback_Type type, Evas_Event_Cb func) EINA_ARG_NONNULL(1, 3); + EAPI void *evas_event_callback_del_full (Evas *e, Evas_Callback_Type type, Evas_Event_Cb func, const void *data) EINA_ARG_NONNULL(1, 3); + EAPI void evas_post_event_callback_push (Evas *e, Evas_Object_Event_Post_Cb func, const void *data); + EAPI void evas_post_event_callback_remove (Evas *e, Evas_Object_Event_Post_Cb func); + EAPI void evas_post_event_callback_remove_full (Evas *e, Evas_Object_Event_Post_Cb func, const void *data); + /** * @defgroup Evas_Image_Group Image Functions * diff --git a/legacy/evas/src/lib/canvas/evas_callbacks.c b/legacy/evas/src/lib/canvas/evas_callbacks.c index fb903144ca..30ea8e5de9 100644 --- a/legacy/evas/src/lib/canvas/evas_callbacks.c +++ b/legacy/evas/src/lib/canvas/evas_callbacks.c @@ -5,6 +5,37 @@ static void evas_object_event_callback_clear(Evas_Object *obj); static void evas_event_callback_clear(Evas *e); int _evas_event_counter = 0; +void +_evas_post_event_callback_call(Evas *e) +{ + Evas_Post_Callback *pc; + int skip = 0; + + if (e->delete_me) return; + _evas_walk(e); + EINA_LIST_FREE(e->post_events, pc) + { + if ((!skip) && (!e->delete_me) && (!pc->delete_me)) + { + if (!pc->func(e, pc->data)) skip = 1; + } + free(pc); + } + _evas_unwalk(e); +} + +void +_evas_post_event_callback_free(Evas *e) +{ + Evas_Post_Callback *pc; + + EINA_LIST_FREE(e->post_events, pc) + { + free(pc); + } + _evas_unwalk(e); +} + void evas_event_callback_list_post_free(Eina_Inlist **list) { @@ -748,6 +779,109 @@ evas_event_callback_del_full(Evas *e, Evas_Callback_Type type, Evas_Event_Cb fun return NULL; } +/** + * Push a callback on the post-event callback stack + * + * @param e Canvas to push the callback on + * @param func The function that to be called when the stack is unwound + * @param data The data pointer to be passed to the callback + * + * Evas has a stack of callbacks that get called after all the callbacks for + * an event have triggered (all the objects it triggers on and al the callbacks + * in each object triggered). When all these have been called, the stack is + * unwond from most recently to least recently pushed item and removed from the + * stack calling the callback set for it. + * + * This is intended for doing reverse logic-like processing, example - when a + * child object that happens to get the event later is meant to be able to + * "steal" functions from a parent and thus on unwind of this stack hav its + * function called first, thus being able to set flags, or return 0 from the + * post-callback that stops all other post-callbacks in the current stack from + * being called (thus basically allowing a child to take control, if the event + * callback prepares information ready for taking action, but the post callback + * actually does the action). + * + */ +EAPI void +evas_post_event_callback_push(Evas *e, Evas_Object_Event_Post_Cb func, const void *data) +{ + Evas_Post_Callback *pc; + + MAGIC_CHECK(e, Evas, MAGIC_EVAS); + return; + MAGIC_CHECK_END(); + + pc = evas_mem_calloc(sizeof(Evas_Post_Callback)); + if (!pc) return; + if (e->delete_me) return; + + pc->func = func; + pc->data = data; + e->post_events = eina_list_prepend(e->post_events, pc); +} + +/** + * Remove a callback from the post-event callback stack + * + * @param e Canvas to push the callback on + * @param func The function that to be called when the stack is unwound + * + * This removes a callback from the stack added with + * evas_post_event_callback_push(). The first instance of the function in + * the callback stack is removed from being executed when the stack is + * unwound. Further instances may still be run on unwind. + */ +EAPI void +evas_post_event_callback_remove(Evas *e, Evas_Object_Event_Post_Cb func) +{ + Evas_Post_Callback *pc; + Eina_List *l; + + MAGIC_CHECK(e, Evas, MAGIC_EVAS); + return; + MAGIC_CHECK_END(); + + EINA_LIST_FOREACH(e->post_events, l, pc) + { + if (pc->func == func) + { + pc->delete_me = 1; + return; + } + } +} + +/** + * Remove a callback from the post-event callback stack + * + * @param e Canvas to push the callback on + * @param func The function that to be called when the stack is unwound + * @param data The data pointer to be passed to the callback + * + * This removes a callback from the stack added with + * evas_post_event_callback_push(). The first instance of the function and data + * in the callback stack is removed from being executed when the stack is + * unwound. Further instances may still be run on unwind. + */ +EAPI void +evas_post_event_callback_remove_full(Evas *e, Evas_Object_Event_Post_Cb func, const void *data) +{ + Evas_Post_Callback *pc; + Eina_List *l; + + MAGIC_CHECK(e, Evas, MAGIC_EVAS); + return; + MAGIC_CHECK_END(); + + EINA_LIST_FOREACH(e->post_events, l, pc) + { + if ((pc->func == func) && (pc->data == data)) + { + pc->delete_me = 1; + return; + } + } +} /** * @} */ diff --git a/legacy/evas/src/lib/canvas/evas_events.c b/legacy/evas/src/lib/canvas/evas_events.c index 39a3a304b6..76ce007beb 100644 --- a/legacy/evas/src/lib/canvas/evas_events.c +++ b/legacy/evas/src/lib/canvas/evas_events.c @@ -343,6 +343,7 @@ evas_event_feed_mouse_down(Evas *e, int b, Evas_Button_Flags flags, unsigned int } if (copy) eina_list_free(copy); e->last_mouse_down_counter++; + _evas_post_event_callback_call(e); _evas_unwalk(e); } @@ -413,6 +414,7 @@ evas_event_feed_mouse_up(Evas *e, int b, Evas_Button_Flags flags, unsigned int t } if (copy) copy = eina_list_free(copy); e->last_mouse_up_counter++; + _evas_post_event_callback_call(e); } if (!e->pointer.button) @@ -455,6 +457,7 @@ evas_event_feed_mouse_up(Evas *e, int b, Evas_Button_Flags flags, unsigned int t } if (e->delete_me) break; } + _evas_post_event_callback_call(e); } if (copy) copy = eina_list_free(copy); if (e->pointer.inside) @@ -489,6 +492,7 @@ evas_event_feed_mouse_up(Evas *e, int b, Evas_Button_Flags flags, unsigned int t } if (e->delete_me) break; } + _evas_post_event_callback_call(e); } else { @@ -603,6 +607,7 @@ evas_event_feed_mouse_wheel(Evas *e, int direction, int z, unsigned int timestam if (e->delete_me) break; } if (copy) copy = eina_list_free(copy); + _evas_post_event_callback_call(e); _evas_unwalk(e); } @@ -695,6 +700,7 @@ evas_event_feed_mouse_move(Evas *e, int x, int y, unsigned int timestamp, const outs = eina_list_append(outs, obj); if (e->delete_me) break; } + _evas_post_event_callback_call(e); } { Evas_Event_Mouse_Out ev; @@ -730,6 +736,7 @@ evas_event_feed_mouse_move(Evas *e, int x, int y, unsigned int timestamp, const evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_OUT, &ev); } } + _evas_post_event_callback_call(e); } } else @@ -820,6 +827,7 @@ evas_event_feed_mouse_move(Evas *e, int x, int y, unsigned int timestamp, const } if (e->delete_me) break; } + _evas_post_event_callback_call(e); _evas_object_event_new(); @@ -844,6 +852,7 @@ evas_event_feed_mouse_move(Evas *e, int x, int y, unsigned int timestamp, const eina_list_free(e->pointer.object.in); /* and set up the new one */ e->pointer.object.in = ins; + _evas_post_event_callback_call(e); } _evas_unwalk(e); } @@ -912,6 +921,7 @@ evas_event_feed_mouse_in(Evas *e, unsigned int timestamp, const void *data) e->pointer.object.in = eina_list_free(e->pointer.object.in); /* and set up the new one */ e->pointer.object.in = ins; + _evas_post_event_callback_call(e); evas_event_feed_mouse_move(e, e->pointer.x, e->pointer.y, timestamp, data); _evas_unwalk(e); } @@ -977,6 +987,7 @@ evas_event_feed_mouse_out(Evas *e, unsigned int timestamp, const void *data) if (copy) copy = eina_list_free(copy); /* free our old list of ins */ e->pointer.object.in = eina_list_free(e->pointer.object.in); + _evas_post_event_callback_call(e); } _evas_unwalk(e); } @@ -1040,6 +1051,7 @@ evas_event_feed_multi_down(Evas *e, if (e->delete_me) break; } if (copy) eina_list_free(copy); + _evas_post_event_callback_call(e); _evas_unwalk(e); } @@ -1102,7 +1114,7 @@ evas_event_feed_multi_up(Evas *e, if (e->delete_me) break; } if (copy) copy = eina_list_free(copy); - + _evas_post_event_callback_call(e); _evas_unwalk(e); } @@ -1174,6 +1186,7 @@ evas_event_feed_multi_move(Evas *e, } if (e->delete_me) break; } + _evas_post_event_callback_call(e); } else { @@ -1240,6 +1253,7 @@ evas_event_feed_multi_move(Evas *e, eina_list_free(e->pointer.object.in); /* and set up the new one */ e->pointer.object.in = ins; + _evas_post_event_callback_call(e); } _evas_unwalk(e); } @@ -1332,8 +1346,9 @@ evas_event_feed_key_down(Evas *e, const char *keyname, const char *key, const ch if ((e->focused) && (!exclusive)) { if (e->events_frozen <= 0) - evas_object_event_callback_call(e->focused, EVAS_CALLBACK_KEY_DOWN, &ev); + evas_object_event_callback_call(e->focused, EVAS_CALLBACK_KEY_DOWN, &ev); } + _evas_post_event_callback_call(e); } _evas_unwalk(e); } @@ -1426,8 +1441,9 @@ evas_event_feed_key_up(Evas *e, const char *keyname, const char *key, const char if ((e->focused) && (!exclusive)) { if (e->events_frozen <= 0) - evas_object_event_callback_call(e->focused, EVAS_CALLBACK_KEY_UP, &ev); + evas_object_event_callback_call(e->focused, EVAS_CALLBACK_KEY_UP, &ev); } + _evas_post_event_callback_call(e); } _evas_unwalk(e); } @@ -1473,8 +1489,8 @@ evas_event_feed_hold(Evas *e, int hold, unsigned int timestamp, const void *data if (e->delete_me) break; } if (copy) copy = eina_list_free(copy); + _evas_post_event_callback_call(e); _evas_unwalk(e); - _evas_object_event_new(); } diff --git a/legacy/evas/src/lib/canvas/evas_focus.c b/legacy/evas/src/lib/canvas/evas_focus.c index 6e2ec5bb02..d63219ab1c 100644 --- a/legacy/evas/src/lib/canvas/evas_focus.c +++ b/legacy/evas/src/lib/canvas/evas_focus.c @@ -39,7 +39,7 @@ evas_object_focus_set(Evas_Object *obj, Eina_Bool focus) if (focus) { - if (obj->focused) return; + if (obj->focused) goto end; if (obj->layer->evas->focused) evas_object_focus_set(obj->layer->evas->focused, 0); obj->focused = 1; @@ -48,11 +48,13 @@ evas_object_focus_set(Evas_Object *obj, Eina_Bool focus) } else { - if (!obj->focused) return; + if (!obj->focused) goto end; obj->focused = 0; obj->layer->evas->focused = NULL; evas_object_event_callback_call(obj, EVAS_CALLBACK_FOCUS_OUT, NULL); } + end: + _evas_post_event_callback_call(obj->layer->evas); } /** diff --git a/legacy/evas/src/lib/canvas/evas_main.c b/legacy/evas/src/lib/canvas/evas_main.c index 56cb652462..c60cb2152d 100644 --- a/legacy/evas/src/lib/canvas/evas_main.c +++ b/legacy/evas/src/lib/canvas/evas_main.c @@ -194,6 +194,8 @@ evas_free(Evas *e) e->callbacks = NULL; } + _evas_post_event_callback_free(e); + del = 1; e->walking_list++; e->cleanup = 1; diff --git a/legacy/evas/src/lib/canvas/evas_object_inform.c b/legacy/evas/src/lib/canvas/evas_object_inform.c index 8fbd040e58..90ead99ae5 100644 --- a/legacy/evas/src/lib/canvas/evas_object_inform.c +++ b/legacy/evas/src/lib/canvas/evas_object_inform.c @@ -9,6 +9,7 @@ evas_object_inform_call_show(Evas_Object *obj) _evas_object_event_new(); evas_object_event_callback_call(obj, EVAS_CALLBACK_SHOW, NULL); + _evas_post_event_callback_call(obj->layer->evas); } void @@ -17,6 +18,7 @@ evas_object_inform_call_hide(Evas_Object *obj) _evas_object_event_new(); evas_object_event_callback_call(obj, EVAS_CALLBACK_HIDE, NULL); + _evas_post_event_callback_call(obj->layer->evas); } void @@ -25,6 +27,7 @@ evas_object_inform_call_move(Evas_Object *obj) _evas_object_event_new(); evas_object_event_callback_call(obj, EVAS_CALLBACK_MOVE, NULL); + _evas_post_event_callback_call(obj->layer->evas); } void @@ -33,6 +36,7 @@ evas_object_inform_call_resize(Evas_Object *obj) _evas_object_event_new(); evas_object_event_callback_call(obj, EVAS_CALLBACK_RESIZE, NULL); + _evas_post_event_callback_call(obj->layer->evas); } void @@ -41,6 +45,7 @@ evas_object_inform_call_restack(Evas_Object *obj) _evas_object_event_new(); evas_object_event_callback_call(obj, EVAS_CALLBACK_RESTACK, NULL); + _evas_post_event_callback_call(obj->layer->evas); } void @@ -49,6 +54,7 @@ evas_object_inform_call_changed_size_hints(Evas_Object *obj) _evas_object_event_new(); evas_object_event_callback_call(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, NULL); + _evas_post_event_callback_call(obj->layer->evas); } void @@ -57,4 +63,5 @@ evas_object_inform_call_image_preloaded(Evas_Object *obj) _evas_object_event_new(); evas_object_event_callback_call(obj, EVAS_CALLBACK_IMAGE_PRELOADED, NULL); + _evas_post_event_callback_call(obj->layer->evas); } diff --git a/legacy/evas/src/lib/canvas/evas_object_main.c b/legacy/evas/src/lib/canvas/evas_object_main.c index 2dc21041af..8173d4ad0f 100644 --- a/legacy/evas/src/lib/canvas/evas_object_main.c +++ b/legacy/evas/src/lib/canvas/evas_object_main.c @@ -371,6 +371,7 @@ evas_object_del(Evas_Object *obj) _evas_object_event_new(); evas_object_event_callback_call(obj, EVAS_CALLBACK_DEL, NULL); + _evas_post_event_callback_call(obj->layer->evas); if (obj->name) evas_object_name_set(obj, NULL); if (!obj->layer) { @@ -383,6 +384,7 @@ evas_object_del(Evas_Object *obj) obj->layer->evas->focused = NULL; _evas_object_event_new(); evas_object_event_callback_call(obj, EVAS_CALLBACK_FOCUS_OUT, NULL); + _evas_post_event_callback_call(obj->layer->evas); } obj->layer->evas->pointer.mouse_grabbed -= obj->mouse_grabbed; obj->mouse_grabbed = 0; @@ -394,6 +396,7 @@ evas_object_del(Evas_Object *obj) evas_object_map_set(obj, NULL); _evas_object_event_new(); evas_object_event_callback_call(obj, EVAS_CALLBACK_FREE, NULL); + _evas_post_event_callback_call(obj->layer->evas); evas_object_smart_cleanup(obj); obj->delete_me = 1; evas_object_change(obj); @@ -1174,6 +1177,7 @@ evas_object_hide(Evas_Object *obj) ev.timestamp = obj->layer->evas->last_timestamp; ev.event_flags = EVAS_EVENT_FLAG_NONE; evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_OUT, &ev); + _evas_post_event_callback_call(obj->layer->evas); } } } diff --git a/legacy/evas/src/lib/include/evas_private.h b/legacy/evas/src/lib/include/evas_private.h index 88ee0b2bc1..2c0185799e 100644 --- a/legacy/evas/src/lib/include/evas_private.h +++ b/legacy/evas/src/lib/include/evas_private.h @@ -50,6 +50,7 @@ typedef struct _Evas_Callbacks Evas_Callbacks; typedef struct _Evas_Format Evas_Format; typedef struct _Evas_Map_Point Evas_Map_Point; typedef struct _Evas_Smart_Cb_Description_Array Evas_Smart_Cb_Description_Array; +typedef struct _Evas_Post_Callback Evas_Post_Callback; #define MAGIC_EVAS 0x70777770 #define MAGIC_OBJ 0x71777770 @@ -213,6 +214,14 @@ struct _Evas_Lock Evas_Modifier_Mask mask; /* we have a max of 64 locks */ }; +struct _Evas_Post_Callback +{ + Evas_Object *obj; + Evas_Object_Event_Post_Cb func; + const void *data; + unsigned char delete_me : 1; +}; + struct _Evas_Callbacks { Eina_Inlist *callbacks; @@ -304,6 +313,8 @@ struct _Evas Eina_Array calculate_objects; Eina_Array clip_changes; + Eina_List *post_events; // free me on evas_free + Evas_Callbacks *callbacks; int delete_grabs; @@ -790,6 +801,8 @@ void evas_object_smart_member_stack_below(Evas_Object *member, Evas_Object *othe const Eina_Inlist *evas_object_smart_members_get_direct(const Evas_Object *obj); void evas_call_smarts_calculate(Evas *e); void *evas_mem_calloc(int size); +void _evas_post_event_callback_call(Evas *e); +void _evas_post_event_callback_free(Evas *e); void evas_event_callback_list_post_free(Eina_Inlist **list); void evas_object_event_callback_all_del(Evas_Object *obj); void evas_object_event_callback_cleanup(Evas_Object *obj);