diff --git a/legacy/elementary/src/bin/test_focus.c b/legacy/elementary/src/bin/test_focus.c index fb66ac0e42..22072a5fc5 100644 --- a/legacy/elementary/src/bin/test_focus.c +++ b/legacy/elementary/src/bin/test_focus.c @@ -5,6 +5,23 @@ #endif #ifndef ELM_LIB_QUICKLAUNCH +static Eina_Bool +_event(void *data __UNUSED__, Evas_Object *obj __UNUSED__, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info) +{ + const char *key; + if (type == EVAS_CALLBACK_KEY_DOWN) + printf ("Key Down:"); + else if (type == EVAS_CALLBACK_KEY_UP) + printf ("Key Up:"); + else + return EINA_FALSE; + Evas_Event_Key_Down *ev = event_info; + printf("%s\n", ev->key); + + ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; + return EINA_TRUE; +} + static void _on_key_down(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *einfo __UNUSED__) { @@ -31,6 +48,7 @@ test_focus(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info elm_win_title_set(win, "Focus"); elm_win_focus_highlight_enabled_set(win, EINA_TRUE); evas_object_resize(win, 800, 600); + elm_object_event_callback_add(win, _event, NULL); elm_win_autodel_set(win, EINA_TRUE); my_show(win); @@ -126,8 +144,10 @@ test_focus(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(bt, 0.0, 0.0); + elm_object_event_callback_add(bt, _event, NULL); elm_scroller_content_set(sc, bt); my_show(bt); + elm_object_event_callback_del(bt, _event, NULL); } } diff --git a/legacy/elementary/src/lib/Elementary.h.in b/legacy/elementary/src/lib/Elementary.h.in index 6cab9fee38..fad056b3e3 100644 --- a/legacy/elementary/src/lib/Elementary.h.in +++ b/legacy/elementary/src/lib/Elementary.h.in @@ -215,8 +215,9 @@ extern "C" { * set on Elm_List_Item, then it is of this type. */ typedef Evas_Object *(*Elm_Tooltip_Item_Content_Cb) (void *data, Evas_Object *obj, void *item); - - + + typedef Eina_Bool (*Elm_Event_Cb) (void *data, Evas_Object *obj, Evas_Object *src, Evas_Callback_Type type, void *event_info); + #ifndef ELM_LIB_QUICKLAUNCH #define ELM_MAIN() int main(int argc, char **argv) {elm_init(argc, argv); return elm_main(argc, argv);} #else @@ -368,6 +369,9 @@ extern "C" { EAPI void elm_object_signal_callback_add(Evas_Object *obj, const char *emission, const char *source, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source), void *data); EAPI void *elm_object_signal_callback_del(Evas_Object *obj, const char *emission, const char *source, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source)); + EAPI void elm_object_event_callback_add(Evas_Object *obj, Elm_Event_Cb func, const void *data); + EAPI void *elm_object_event_callback_del(Evas_Object *obj, Elm_Event_Cb func, const void *data); + EAPI void elm_coords_finger_size_adjust(int times_w, Evas_Coord *w, int times_h, Evas_Coord *h); EAPI double elm_longpress_timeout_get(void); diff --git a/legacy/elementary/src/lib/elm_main.c b/legacy/elementary/src/lib/elm_main.c index 82901676ad..93c39ff40e 100644 --- a/legacy/elementary/src/lib/elm_main.c +++ b/legacy/elementary/src/lib/elm_main.c @@ -2651,6 +2651,50 @@ elm_object_signal_callback_del(Evas_Object *obj, const char *emission, const cha return elm_widget_signal_callback_del(obj, emission, source, func); } +/** + * Add a callback for a event emitted by widget or their children. + * + * This function connects a callback function to any key_down key_up event + * emitted by the @p obj or their children. + * This only will be called if no other callback has consumed the event. + * If you want consume the event, and no other get it, func should return + * EINA_TRUE and put EVAS_EVENT_FLAG_ON_HOLD in event_flags. + * + * @warning Accept duplicated callback addition. + * + * @param obj The object + * @param func The callback function to be executed when the event is + * emitted. + * @param data Data to pass in to the callback function. + * @ingroup General + */ +EAPI void +elm_object_event_callback_add(Evas_Object *obj, Elm_Event_Cb func, const void *data) +{ + elm_widget_event_callback_add(obj, func, data); +} + +/** + * Remove a event callback from an widget. + * + * This function removes a callback, previoulsy attached to event emission + * by the @p obj. + * The parameters func and data must match exactly those passed to + * a previous call to elm_object_event_callback_add(). The data pointer that + * was passed to this call will be returned. + * + * @param obj The object + * @param func The callback function to be executed when the event is + * emitted. + * @param data Data to pass in to the callback function. + * @return The data pointer + * @ingroup General + */ +EAPI void * +elm_object_event_callback_del(Evas_Object *obj, Elm_Event_Cb func, const void *data) +{ + return elm_widget_event_callback_del(obj, func, data); +} /** diff --git a/legacy/elementary/src/lib/elm_widget.c b/legacy/elementary/src/lib/elm_widget.c index c5eb513128..93957495d2 100644 --- a/legacy/elementary/src/lib/elm_widget.c +++ b/legacy/elementary/src/lib/elm_widget.c @@ -12,6 +12,7 @@ static const char SMART_NAME[] = "elm_widget"; typedef struct _Smart_Data Smart_Data; typedef struct _Edje_Signal_Data Edje_Signal_Data; +typedef struct _Elm_Event_Cb_Data Elm_Event_Cb_Data; struct _Smart_Data { @@ -77,6 +78,7 @@ struct _Smart_Data Eina_Bool disabled : 1; Eina_List *focus_chain; + Eina_List *event_cb; }; struct _Edje_Signal_Data @@ -88,6 +90,11 @@ struct _Edje_Signal_Data void *data; }; +struct _Elm_Event_Cb_Data { + Elm_Event_Cb func; + const void *data; +}; + /* local subsystem functions */ static void _smart_reconfigure(Smart_Data *sd); static void _smart_add(Evas_Object *obj); @@ -238,13 +245,7 @@ _propagate_event(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_i break; } - if ((event_flags) && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD)) - return; - - if ((sd->event_func) && (sd->event_func(obj, obj, type, event_info))) - return; - - elm_widget_parent_event_propagate(obj, type, event_info, event_flags); + elm_widget_event_propagate(obj, type, event_info, event_flags); } static void @@ -897,11 +898,40 @@ elm_widget_parent_widget_get(const Evas_Object *obj) return parent; } -EAPI Eina_Bool -elm_widget_parent_event_propagate(Evas_Object *obj, Evas_Callback_Type type, void *event_info, Evas_Event_Flags *event_flags) +EAPI void +elm_widget_event_callback_add(Evas_Object *obj, Elm_Event_Cb func, const void *data) { - API_ENTRY return EINA_FALSE; - Evas_Object *parent = sd->parent_obj; + API_ENTRY return; + Elm_Event_Cb_Data *ecb = ELM_NEW(Elm_Event_Cb_Data); + ecb->func = func; + ecb->data = data; + sd->event_cb = eina_list_append(sd->event_cb, ecb); +} + +EAPI void * +elm_widget_event_callback_del(Evas_Object *obj, Elm_Event_Cb func, const void *data) +{ + API_ENTRY return NULL; + Eina_List *l; + Elm_Event_Cb_Data *ecd; + EINA_LIST_FOREACH(sd->event_cb, l, ecd) + if ((ecd->func == func) && (ecd->data == data)) + { + free(ecd); + sd->event_cb = eina_list_remove_list(sd->event_cb, l); + return (void *)data; + } + return NULL; +} + +EAPI Eina_Bool +elm_widget_event_propagate(Evas_Object *obj, Evas_Callback_Type type, void *event_info, Evas_Event_Flags *event_flags) +{ + API_ENTRY return EINA_FALSE; //TODO reduce. + if (!_elm_widget_is(obj)) return EINA_FALSE; + Evas_Object *parent = obj; + Elm_Event_Cb_Data *ecd; + Eina_List *l, *l_prev; while (parent && (!(event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD)))) @@ -909,8 +939,16 @@ elm_widget_parent_event_propagate(Evas_Object *obj, Evas_Callback_Type type, voi sd = evas_object_smart_data_get(parent); if ((!sd) || (!_elm_widget_is(obj))) return EINA_FALSE; //Not Elm Widget + if (sd->event_func && (sd->event_func(parent, obj, type, event_info))) return EINA_TRUE; + + EINA_LIST_FOREACH_SAFE(sd->event_cb, l, l_prev, ecd) + { + if (ecd->func((void *)ecd->data, parent, obj, type, event_info) || + (event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD))) + return EINA_TRUE; + } parent = sd->parent_obj; } @@ -2499,7 +2537,7 @@ _smart_del(Evas_Object *obj) Edje_Signal_Data *esd; INTERNAL_ENTRY; - + if (sd->del_pre_func) sd->del_pre_func(obj); if (sd->resize_obj) { @@ -2531,6 +2569,7 @@ _smart_del(Evas_Object *obj) eina_stringshare_del(esd->source); free(esd); } + eina_list_free(sd->event_cb); /* should be empty anyway */ if (sd->del_func) sd->del_func(obj); if (sd->style) eina_stringshare_del(sd->style); if (sd->type) eina_stringshare_del(sd->type); diff --git a/legacy/elementary/src/lib/elm_widget.h b/legacy/elementary/src/lib/elm_widget.h index d6a5646cb2..618e6e7440 100644 --- a/legacy/elementary/src/lib/elm_widget.h +++ b/legacy/elementary/src/lib/elm_widget.h @@ -247,7 +247,9 @@ EAPI Evas_Object *elm_widget_focused_object_get(const Evas_Object *obj); EAPI Evas_Object *elm_widget_top_get(const Evas_Object *obj); EAPI Eina_Bool elm_widget_is(const Evas_Object *obj); EAPI Evas_Object *elm_widget_parent_widget_get(const Evas_Object *obj); -EAPI Eina_Bool elm_widget_parent_event_propagate(Evas_Object *obj, Evas_Callback_Type type, void *event_info, Evas_Event_Flags *event_flags); +EAPI void elm_widget_event_callback_add(Evas_Object *obj, Elm_Event_Cb func, const void *data); +EAPI void *elm_widget_event_callback_del(Evas_Object *obj, Elm_Event_Cb func, const void *data); +EAPI Eina_Bool elm_widget_event_propagate(Evas_Object *obj, Evas_Callback_Type type, void *event_info, Evas_Event_Flags *event_flags); EAPI void elm_widget_focus_custom_chain_set(Evas_Object *obj, Eina_List *objs); EAPI void elm_widget_focus_custom_chain_unset(Evas_Object *obj); EAPI const Eina_List *elm_widget_focus_custom_chain_get(const Evas_Object *obj);