From e3c218425dcfdc07c9157f213744ca57cc6710dc Mon Sep 17 00:00:00 2001 From: Thiep Ha Date: Tue, 9 Jan 2018 18:50:23 +0900 Subject: [PATCH] cnp_dnd: make legacy APIs use new interfaces Legacy APIs can uses efl_selection, efl_ui_dnd, efl_ui_dnd_container interfaces with helper functions. --- src/Makefile_Elementary.am | 1 - src/lib/elementary/efl_selection.c | 241 ++++++++++ src/lib/elementary/efl_selection_manager.c | 90 ++-- src/lib/elementary/efl_ui_dnd.c | 678 +++++++++++++++++++++++++++++ 4 files changed, 963 insertions(+), 47 deletions(-) diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am index 8af7e31..c8eb01b 100644 --- a/src/Makefile_Elementary.am +++ b/src/Makefile_Elementary.am @@ -626,7 +626,6 @@ lib_elementary_libelementary_la_SOURCES = \ lib/elementary/efl_ui_calendar.c \ lib/elementary/efl_ui_check.c \ lib/elementary/elm_clock.c \ - lib/elementary/elm_cnp.c \ lib/elementary/elm_code_line.c \ lib/elementary/elm_code_text.c \ lib/elementary/elm_code_indent.c \ diff --git a/src/lib/elementary/efl_selection.c b/src/lib/elementary/efl_selection.c index 9f086e3..00cfe13 100644 --- a/src/lib/elementary/efl_selection.c +++ b/src/lib/elementary/efl_selection.c @@ -59,4 +59,245 @@ _efl_selection_has_owner(Eo *obj, void *pd EINA_UNUSED, Efl_Selection_Type type, } +////////// Support legacy APIs + +//TODO: Clear this list (when sel_man is deleted) +Eina_List *lost_cb_list = NULL; + +#ifdef HAVE_ELEMENTARY_WL2 +static Ecore_Wl2_Window * +_wl_window_get(const Evas_Object *obj) +{ + Evas_Object *top; + Ecore_Wl2_Window *win = NULL; + + if (elm_widget_is(obj)) + { + top = elm_widget_top_get(obj); + if (!top) top = elm_widget_top_get(elm_widget_parent_widget_get(obj)); + if (top && (efl_isa(top, EFL_UI_WIN_CLASS))) + win = elm_win_wl_window_get(top); + } + if (!win) + { + Ecore_Evas *ee; + Evas *evas; + const char *engine_name; + + if (!(evas = evas_object_evas_get(obj))) + return NULL; + if (!(ee = ecore_evas_ecore_evas_get(evas))) + return NULL; + + engine_name = ecore_evas_engine_name_get(ee); + if (!strcmp(engine_name, ELM_BUFFER)) + { + ee = ecore_evas_buffer_ecore_evas_parent_get(ee); + if (!ee) return NULL; + engine_name = ecore_evas_engine_name_get(ee); + } + if (!strncmp(engine_name, "wayland", sizeof("wayland") - 1)) + { + /* In case the engine is not a buffer, we want to check once. */ + win = ecore_evas_wayland2_window_get(ee); + if (!win) return NULL; + } + } + + return win; +} + +int _wl_default_seat_id_get(Evas_Object *obj) +{ + Ecore_Wl2_Window *win = _wl_window_get(obj); + Eo *seat, *parent2, *ewin; + + if (obj) + { + Eo *top = elm_widget_top_get(obj); + if (efl_isa(top, EFL_UI_WIN_INLINED_CLASS)) + { + parent2 = efl_ui_win_inlined_parent_get(top); + if (parent2) obj = elm_widget_top_get(parent2) ?: parent2; + } + /* fake win means canvas seat id will not match protocol seat id */ + ewin = elm_win_get(obj); + if (elm_win_type_get(ewin) == ELM_WIN_FAKE) obj = NULL; + } + + if (!obj) + { + Ecore_Wl2_Input *input; + Eina_Iterator *it; + + it = ecore_wl2_display_inputs_get(ecore_wl2_window_display_get(win)); + EINA_ITERATOR_FOREACH(it, input) break; + eina_iterator_free(it); + if (input) + ecore_wl2_input_seat_id_get(input); + } + + seat = evas_default_device_get(evas_object_evas_get(obj), EFL_INPUT_DEVICE_TYPE_SEAT); + EINA_SAFETY_ON_NULL_RETURN_VAL(seat, 1); + return evas_device_seat_id_get(seat); +} +#endif + +typedef struct _Cnp_Data_Cb_Wrapper Cnp_Data_Cb_Wrapper; +struct _Cnp_Data_Cb_Wrapper +{ + void *udata; + Elm_Drop_Cb datacb; +}; + +static void +_selection_data_ready_cb(void *data, Efl_Object *obj, Efl_Selection_Data *seldata) +{ + printf("obj: %p, data: %s, length: %zd\n", obj, (char *)seldata->data.mem, seldata->data.len); + Cnp_Data_Cb_Wrapper *wdata = data; + if (!wdata) return; + Elm_Selection_Data ddata; + + ddata.data = calloc(1, seldata->data.len + 1); + if (!ddata.data) return; + ddata.data = memcpy(ddata.data, seldata->data.mem, seldata->data.len); + ddata.len = seldata->data.len; + ddata.x = seldata->pos.x; + ddata.y = seldata->pos.y; + ddata.format = seldata->format; + ddata.action = seldata->action; + wdata->datacb(wdata->udata, obj, &ddata); + free(ddata.data); +} + +typedef struct _Sel_Lost_Data Sel_Lost_Data; +struct _Sel_Lost_Data +{ + const Evas_Object *obj; + Elm_Sel_Type type; + void *udata; + Elm_Selection_Loss_Cb loss_cb; +}; + +static Eina_Value +_selection_lost_cb(void *data, const Eina_Value value) +{ + Eina_List *l, *l2; + Sel_Lost_Data *ldata, *ldata2; + + ldata = data; + EINA_LIST_FOREACH_SAFE(lost_cb_list, l, l2, ldata2) + { + if ((ldata->obj == ldata2->obj) && + (ldata->type == ldata2->type)) + { + ldata2->loss_cb(ldata2->udata, ldata2->type); + lost_cb_list = eina_list_remove(lost_cb_list, ldata2); + } + } + free(ldata); + + return value; +} + +EAPI Eina_Bool +elm_cnp_selection_get(const Evas_Object *obj, Elm_Sel_Type type, + Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata) +{ + int seatid = 1; + Eo *sel_man = _selection_manager_get((Evas_Object *)obj); + Cnp_Data_Cb_Wrapper *wdata = calloc(1, sizeof(Cnp_Data_Cb_Wrapper)); + + if (!wdata) return EINA_FALSE; + +#ifdef HAVE_ELEMENTARY_WL2 + seatid = _wl_default_seat_id_get(obj); +#endif + wdata->udata = udata; + wdata->datacb = datacb; + efl_selection_manager_selection_get(sel_man, (Evas_Object *)obj, type, format, + wdata, _selection_data_ready_cb, NULL, seatid); + return EINA_TRUE; +} + +EAPI Eina_Bool +elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type type, + Elm_Sel_Format format, const void *selbuf, size_t buflen) +{ + int seatid = 1; + Eina_Future *f; + Sel_Lost_Data *ldata; + Eo *sel_man = _selection_manager_get(obj); + Eina_Slice data; + + ldata = calloc(1, sizeof(Sel_Lost_Data)); + if (!ldata) return EINA_FALSE; + data.mem = selbuf; + data.len = buflen; +#ifdef HAVE_ELEMENTARY_WL2 + seatid = _wl_default_seat_id_get(obj); +#endif + f = efl_selection_manager_selection_set(sel_man, obj, type, format, data, seatid); + + ldata->obj = obj; + ldata->type = type; + eina_future_then_easy(f, _selection_lost_cb, NULL, NULL, EINA_VALUE_TYPE_UINT, ldata); + + return EINA_TRUE; +} + +EAPI Eina_Bool +elm_object_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type type) +{ + int seatid = 1; + Eo *sel_man = _selection_manager_get((Evas_Object *)obj); + +#ifdef HAVE_ELEMENTARY_WL2 + seatid = _wl_default_seat_id_get(obj); +#endif + efl_selection_manager_selection_clear(sel_man, obj, type, seatid); + + return EINA_TRUE; +} + +EAPI void +elm_cnp_selection_loss_callback_set(Evas_Object *obj, Elm_Sel_Type type, + Elm_Selection_Loss_Cb func, const void *data) +{ + Sel_Lost_Data *ldata = calloc(1, sizeof(Sel_Lost_Data)); + if (!ldata) return; + ldata->obj = obj; + ldata->type = type; + ldata->udata = (void *)data; + ldata->loss_cb = func; + lost_cb_list = eina_list_append(lost_cb_list, ldata); +} + +EAPI Eina_Bool +elm_selection_selection_has_owner(Evas_Object *obj) +{ + int seatid = 1; + Eo *sel_man = _selection_manager_get((Evas_Object *)obj); + +#ifdef HAVE_ELEMENTARY_WL2 + seatid = _wl_default_seat_id_get(obj); +#endif + + return efl_selection_manager_selection_has_owner(sel_man, obj, + EFL_SELECTION_TYPE_CLIPBOARD, seatid); +} + +EAPI Eina_Bool +elm_cnp_clipboard_selection_has_owner(Evas_Object *obj) +{ + int seatid = 1; + Eo *sel_man = _selection_manager_get((Evas_Object *)obj); + +#ifdef HAVE_ELEMENTARY_WL2 + seatid = _wl_default_seat_id_get(obj); +#endif + return efl_selection_manager_selection_has_owner(sel_man, obj, + EFL_SELECTION_TYPE_CLIPBOARD, seatid); +} + #include "efl_selection.eo.c" diff --git a/src/lib/elementary/efl_selection_manager.c b/src/lib/elementary/efl_selection_manager.c index 91cc4a6..bcb79aa 100644 --- a/src/lib/elementary/efl_selection_manager.c +++ b/src/lib/elementary/efl_selection_manager.c @@ -19,7 +19,6 @@ # define sel_debug(x...) do { } while (0) #endif -static void _set_selection_list(Sel_Manager_Selection *sel_list, Sel_Manager_Seat_Selection *seat_sel); static void _anim_data_free(Sel_Manager_Drag_Container *dc); static void _cont_obj_mouse_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info); static void _cont_obj_mouse_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info); @@ -30,13 +29,18 @@ void efl_selection_manager_selection_clear(Eo *obj, Efl_Object *owner, Efl_Selec void efl_selection_manager_drag_start(Eo *obj, Efl_Object *drag_obj, Efl_Selection_Format format, Eina_Slice data, Efl_Selection_Action action, void *icon_func_data, Efl_Dnd_Drag_Icon_Create icon_func, Eina_Free_Cb icon_func_free_cb, unsigned int seat); #ifdef HAVE_ELEMENTARY_X +static void _set_selection_list(Sel_Manager_Selection *sel_list, Sel_Manager_Seat_Selection *seat_sel); static Ecore_X_Atom _x11_dnd_action_rev_map(Efl_Selection_Action action); static Ecore_X_Window _x11_xwin_get(const Evas_Object *obj); #endif #ifdef HAVE_ELEMENTARY_WL2 static Ecore_Wl2_Window *_wl_window_get(const Evas_Object *obj); -static Ecore_Wl2_Input *_wl_seat_get(Ecore_Wl2_Window *win, const Evas_Object *obj, unsigned int seat_id); +static Ecore_Wl2_Input *_wl_seat_get(Ecore_Wl2_Window *win, Evas_Object *obj, unsigned int seat_id); +#endif + +#ifdef HAVE_ELEMENTARY_WIN32 +static void _set_selection_list(Sel_Manager_Selection *sel_list, Sel_Manager_Seat_Selection *seat_sel); #endif static inline void @@ -157,6 +161,37 @@ _sel_manager_seat_selection_init(Efl_Selection_Manager_Data *pd, unsigned int se return seat_sel; } +static void +_sel_manager_promise_cancel(void *data, const Eina_Promise *dead_future EINA_UNUSED) +{ + Sel_Manager_Selection_Lost *sel_lost = data; + //FIXME: remove from sel_lost_list in seat_sel + free(sel_lost); +} + +static inline Eina_Future * +_update_sel_lost_list(Efl_Object *obj, Efl_Selection_Type type, + Sel_Manager_Seat_Selection *seat_sel) +{ + Eina_Promise *p; + Sel_Manager_Selection_Lost *sel_lost; + + sel_lost = calloc(1, sizeof(Sel_Manager_Selection_Lost)); + if (!sel_lost) + return NULL; + sel_lost->request = obj; + sel_lost->type = type; + seat_sel->sel_lost_list = eina_list_append(seat_sel->sel_lost_list, sel_lost); + + p = eina_promise_new(efl_loop_future_scheduler_get(obj), + _sel_manager_promise_cancel, NULL); + eina_promise_data_set(p, sel_lost); + if (!p) return NULL; + sel_lost->promise = p; + + return eina_future_new(p); +} + /* TODO: this should not be an actual tempfile, but rather encode the object * as http://dataurl.net/ if it's an image or similar. Evas should support * decoding it as memfile. */ @@ -901,7 +936,6 @@ _x11_selection_clear(void *data, int type EINA_UNUSED, void *event) Eina_List *l, *l_next; Sel_Manager_Selection_Lost *sel_lost; unsigned int i; - ERR("In"); seat_sel = _sel_manager_seat_selection_get(pd, 1); if (!seat_sel) @@ -1082,37 +1116,6 @@ _x11_text_converter(char *target, void *data, int size EINA_UNUSED, void **data_ return EINA_TRUE; } -static void -_sel_manager_promise_cancel(void *data, const Eina_Promise *dead_future EINA_UNUSED) -{ - Sel_Manager_Selection_Lost *sel_lost = data; - //FIXME: remove from sel_lost_list in seat_sel - free(sel_lost); -} - -static inline Eina_Future * -_update_sel_lost_list(Efl_Object *obj, Efl_Selection_Type type, - Sel_Manager_Seat_Selection *seat_sel) -{ - Eina_Promise *p; - Sel_Manager_Selection_Lost *sel_lost; - - sel_lost = calloc(1, sizeof(Sel_Manager_Selection_Lost)); - if (!sel_lost) - return NULL; - sel_lost->request = obj; - sel_lost->type = type; - seat_sel->sel_lost_list = eina_list_append(seat_sel->sel_lost_list, sel_lost); - - p = eina_promise_new(efl_loop_future_scheduler_get(obj), - _sel_manager_promise_cancel, NULL); - eina_promise_data_set(p, sel_lost); - if (!p) return NULL; - sel_lost->promise = p; - - return eina_future_new(p); -} - static Eina_Future * _x11_efl_sel_manager_selection_set(Efl_Selection_Manager_Data *pd, Efl_Object *owner, Efl_Selection_Type type, Efl_Selection_Format format, Eina_Slice data, @@ -1138,7 +1141,7 @@ _x11_efl_sel_manager_selection_set(Efl_Selection_Manager_Data *pd, Efl_Object *o sel->format = format; sel->set(xwin, &sel, sizeof(&sel)); - sel_debug("data: %p (%ld)", &sel, sizeof(&sel)); + sel_debug("data: %p (%zu)", &sel, sizeof(&sel)); return _update_sel_lost_list(owner, type, seat_sel); } @@ -1964,7 +1967,6 @@ _x11_sel_manager_drop_target_add(Efl_Selection_Manager_Data *pd, Efl_Object *tar Efl_Selection_Format format, Ecore_X_Window xwin, unsigned int seat) { - ERR("In"); Sel_Manager_Dropable *dropable = NULL; Eina_List *l; Eina_Bool have_drop_list = EINA_FALSE; @@ -2076,10 +2078,10 @@ _wl_drag_source_del(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj, void * } static void -_wl_efl_sel_manager_drag_start(Eo *obj, Efl_Selection_Manager_Data *pd, Efl_Object *drag_obj, +_wl_efl_sel_manager_drag_start(Eo *obj EINA_UNUSED, Efl_Selection_Manager_Data *pd, Efl_Object *drag_obj, Efl_Selection_Format format, Eina_Slice data, Efl_Selection_Action action, void *icon_func_data, - Efl_Dnd_Drag_Icon_Create icon_func, Eina_Free_Cb icon_func_free_cb, + Efl_Dnd_Drag_Icon_Create icon_func, Eina_Free_Cb icon_func_free_cb EINA_UNUSED, Ecore_Wl2_Window *win, unsigned int seat) { Ecore_Evas *ee; @@ -2481,11 +2483,11 @@ _wl_efl_sel_manager_selection_set(Efl_Selection_Manager_Data *pd, return _update_sel_lost_list(owner, type, seat_sel); } -static void +/*static void _wl_selection_changed_free(void *data, void *ev EINA_UNUSED) { ecore_wl2_display_disconnect(data); -} +}*/ static Eina_Bool _wl_selection_changed(void *data, int type EINA_UNUSED, void *event) @@ -2622,7 +2624,7 @@ _wl_dnd_end(void *data, int type EINA_UNUSED, void *event) } static Ecore_Wl2_Input * -_wl_seat_get(Ecore_Wl2_Window *win, const Evas_Object *obj, unsigned int seat_id) +_wl_seat_get(Ecore_Wl2_Window *win, Evas_Object *obj, unsigned int seat_id) { Eo *seat, *parent2, *ewin; Ecore_Wl2_Input *input = NULL; @@ -2719,7 +2721,6 @@ _wl_selection_receive(void *data, int type EINA_UNUSED, void *event) { Ecore_Wl2_Event_Offer_Data_Ready *ev = event; Sel_Manager_Selection *sel = data; - ERR("in"); if (sel->sel_offer != ev->offer) return ECORE_CALLBACK_PASS_ON; @@ -2783,7 +2784,7 @@ _wl_efl_sel_manager_selection_get(const Efl_Object *request, Efl_Selection_Manag sel->data_func = data_func; sel->data_func_free_cb = data_func_free_cb; - input = _wl_seat_get(win, request, seat_sel->seat); + input = _wl_seat_get(win, (Efl_Object *)request, seat_sel->seat); offer = ecore_wl2_dnd_selection_get(input); //there can be no selection available @@ -4279,7 +4280,6 @@ _drag_anim_play(void *data, double pos) { Sel_Manager_Drag_Container *dc = data; - ERR("In"); if (dc->animator) { Eina_List *l; @@ -4317,7 +4317,6 @@ _drag_anim_play(void *data, double pos) static inline void _drag_anim_start(Sel_Manager_Drag_Container *dc) { - ERR("In"); dc->timer = NULL; if (dc->icon_func) @@ -4904,7 +4903,6 @@ EOLIAN static void _efl_selection_manager_container_drop_item_del(Eo *obj EINA_UNUSED, Efl_Selection_Manager_Data *pd, Efl_Object *cont, unsigned int seat EINA_UNUSED) { - ERR("In"); _drop_item_container_del(pd, cont, EINA_TRUE); } diff --git a/src/lib/elementary/efl_ui_dnd.c b/src/lib/elementary/efl_ui_dnd.c index 731229d..ae27c53 100644 --- a/src/lib/elementary/efl_ui_dnd.c +++ b/src/lib/elementary/efl_ui_dnd.c @@ -132,5 +132,683 @@ _efl_ui_dnd_container_drop_item_del(Eo *obj, Efl_Ui_Dnd_Container_Data *pd EINA_ efl_selection_manager_container_drop_item_del(sel_man, obj, seat); } + +/////////// +typedef struct _Dnd_Icon_Create Dnd_Icon_Create; +typedef struct _Dnd_Drag_Pos Dnd_Drag_Pos; +typedef struct _Dnd_Drag_Accept Dnd_Drag_Accept; +typedef struct _Dnd_Drag_Done Dnd_Drag_Done; +typedef struct _Dnd_Drag_State Dnd_Drag_State; +typedef struct _Dnd_Drop Dnd_Drop; +typedef struct _Dnd_Cont_Drag_Pos Dnd_Cont_Drag_Pos; +typedef struct _Dnd_Cont_Drop Dnd_Cont_Drop; +typedef struct _Item_Container_Drag_Info Item_Container_Drag_Info; + +struct _Dnd_Icon_Create +{ + void *icon_data; + Elm_Drag_Icon_Create_Cb icon_cb; +}; + +struct _Dnd_Drag_Pos +{ + void *pos_data; + Elm_Drag_Pos pos_cb; +}; + +struct _Dnd_Drag_Accept +{ + void *accept_data; + Elm_Drag_Accept accept_cb; +}; + +struct _Dnd_Drag_Done +{ + void *done_data; + Elm_Drag_State done_cb; + + //for deleting + Dnd_Drag_Pos *pos; + Dnd_Drag_Accept *accept; +}; + +struct _Dnd_Drag_State +{ + void *state_data; + Elm_Drag_State state_cb; +}; + +struct _Dnd_Drop +{ + Efl_Object *obj; + Elm_Sel_Format format; + void *drop_data; + Elm_Drop_Cb drop_cb; + + //for deleting + Dnd_Drag_State *enter; + Dnd_Drag_State *leave; + Dnd_Drag_Pos *pos; +}; + +struct _Dnd_Cont_Drag_Pos +{ + void *pos_data; + Elm_Drag_Item_Container_Pos pos_cb; + Elm_Xy_Item_Get_Cb item_get_cb; +}; + +struct _Dnd_Cont_Drop +{ + Efl_Object *obj; + Elm_Sel_Format format; + void *drop_data; + Elm_Drop_Item_Container_Cb drop_cb; + Elm_Xy_Item_Get_Cb item_get_cb; + + //for deleting + Dnd_Drag_State *enter; + Dnd_Drag_State *leave; + Dnd_Cont_Drag_Pos *pos; +}; + +struct _Item_Container_Drag_Info +{ + Elm_Drag_User_Info user_info; + Elm_Object_Item *it; + Elm_Item_Container_Data_Get_Cb data_get_cb; + Elm_Xy_Item_Get_Cb item_get_cb; +}; + +static Efl_Object * +_dnd_icon_create_cb(void *data, Efl_Object *win, Efl_Object *drag_obj EINA_UNUSED, Eina_Position2D *pos_ret) +{ + Dnd_Icon_Create *ic = data; + Efl_Object *ret = ic->icon_cb(ic->icon_data, win, &pos_ret->x, &pos_ret->y); + + free(ic); + return ret; +} + +static void +_dnd_drag_pos_cb(void *data, const Efl_Event *event) +{ + Dnd_Drag_Pos *pos = data; + Efl_Dnd_Drag_Pos *ddata = event->info; + + if (pos->pos_cb) + pos->pos_cb(pos->pos_data, event->object, ddata->pos.x, ddata->pos.y, + ddata->action); +} + +static void +_dnd_drag_accept_cb(void *data, const Efl_Event *event) +{ + Dnd_Drag_Accept *accept = data; + + if (accept->accept_cb) + accept->accept_cb(accept->accept_data, event->object, *(Eina_Bool *)event->info); +} + +static void +_dnd_drag_done_cb(void *data, const Efl_Event *event) +{ + Dnd_Drag_Done *done = data; + + if (done->done_cb) + done->done_cb(done->done_data, event->object); + + efl_event_callback_del(event->object, EFL_UI_DND_EVENT_DRAG_POS, + _dnd_drag_pos_cb, done->pos); + efl_event_callback_del(event->object, EFL_UI_DND_EVENT_DRAG_ACCEPT, + _dnd_drag_accept_cb, done->accept); + efl_event_callback_del(event->object, EFL_UI_DND_EVENT_DRAG_DONE, + _dnd_drag_done_cb, done); + free(done->pos); + free(done->accept); + free(done); +} + +static void +_dnd_drag_enter_leave_cb(void *data, const Efl_Event *event) +{ + Dnd_Drag_State *state = data; + + if (state->state_cb) + state->state_cb(state->state_data, event->object); +} + +static void +_dnd_drop_cb(void *data, const Efl_Event *event) +{ + Dnd_Drop *drop = data; + Efl_Selection_Data *org_ddata = event->info; + Elm_Selection_Data ddata; + + ddata.x = org_ddata->pos.x; + ddata.y = org_ddata->pos.y; + ddata.format = org_ddata->format; + ddata.action = org_ddata->action; + ddata.data = calloc(1, org_ddata->data.len); + if (!ddata.data) return; + ddata.data = memcpy(ddata.data, org_ddata->data.mem, org_ddata->data.len); + ddata.len = org_ddata->data.len; + if (drop->drop_cb) + drop->drop_cb(drop->drop_data, event->object, &ddata); + free(ddata.data); +} + +EAPI Eina_Bool +elm_drag_start(Evas_Object *obj, Elm_Sel_Format format, const char *data, + Elm_Xdnd_Action action, + Elm_Drag_Icon_Create_Cb icon_create_cb, void *icon_create_data, + Elm_Drag_Pos drag_pos_cb, void *drag_pos_data, + Elm_Drag_Accept drag_accept_cb, void *drag_accept_data, + Elm_Drag_State drag_done_cb, void *drag_done_data) +{ + Eo *sel_man = _selection_manager_get(obj); + int seatid = 1; + Eina_Slice sl; + Dnd_Drag_Pos *pos = calloc(1, sizeof(Dnd_Drag_Pos)); + Dnd_Drag_Accept *accept = calloc(1, sizeof(Dnd_Drag_Accept)); + Dnd_Drag_Done *done = calloc(1, sizeof(Dnd_Drag_Done)); + Dnd_Icon_Create *ic = calloc(1, sizeof(Dnd_Icon_Create)); + if (!pos || !accept || !done || !ic) return EINA_FALSE; + + pos->pos_data = drag_pos_data; + pos->pos_cb = drag_pos_cb; + + accept->accept_data = drag_accept_data; + accept->accept_cb = drag_accept_cb; + + done->done_data = drag_done_data; + done->done_cb = drag_done_cb; + done->pos = pos; + done->accept = accept; + + efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_POS, _dnd_drag_pos_cb, pos); + efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_ACCEPT, _dnd_drag_accept_cb, accept); + efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_DONE, _dnd_drag_done_cb, done); + sl.mem = data; + sl.len = strlen(data); +#ifdef HAVE_ELEMENTARY_WL2 + seatid = _wl_default_seat_id_get(obj); +#endif + + ic->icon_data = icon_create_data; + ic->icon_cb = icon_create_cb; + efl_selection_manager_drag_start(sel_man, obj, format, sl, action, + ic, _dnd_icon_create_cb, NULL, seatid); + + return EINA_TRUE; +} + +EAPI Eina_Bool +elm_drag_action_set(Evas_Object *obj, Elm_Xdnd_Action action) +{ + Eo *sel_man = _selection_manager_get(obj); + int seatid = 1; + +#ifdef HAVE_ELEMENTARY_WL2 + seatid = _wl_default_seat_id_get(obj); +#endif + efl_selection_manager_drag_action_set(sel_man, obj, action, seatid); + + return EINA_TRUE; +} + +EAPI Eina_Bool +elm_drag_cancel(Evas_Object *obj) +{ + Eo *sel_man = _selection_manager_get(obj); + int seatid = 1; + +#ifdef HAVE_ELEMENTARY_WL2 + seatid = _wl_default_seat_id_get(obj); +#endif + + efl_selection_manager_drag_cancel(sel_man, obj, seatid); + + return EINA_TRUE; +} + +static void +_drop_obj_del_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Eina_List *drop_list; + Dnd_Drop *drop; + + drop_list = efl_key_data_get(obj, "__drop_list"); + EINA_LIST_FREE(drop_list, drop) + { + efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_ENTER, + _dnd_drag_enter_leave_cb, drop->enter); + efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_LEAVE, + _dnd_drag_enter_leave_cb, drop->leave); + efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_POS, + _dnd_drag_pos_cb, drop->pos); + efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_DROP, + _dnd_drop_cb, drop); + free(drop->enter); + free(drop->leave); + free(drop->pos); + free(drop); + } +} + +EAPI Eina_Bool +elm_drop_target_add(Evas_Object *obj, Elm_Sel_Format format, + Elm_Drag_State enter_cb, void *enter_data, + Elm_Drag_State leave_cb, void *leave_data, + Elm_Drag_Pos pos_cb, void *pos_data, + Elm_Drop_Cb drop_cb, void *drop_data) +{ + Eo *sel_man = _selection_manager_get(obj); + int seatid = 1; + Dnd_Drag_State *enter, *leave; + Dnd_Drag_Pos *pos; + Dnd_Drop *drop; + Eina_List *drop_list; + + enter = calloc(1, sizeof(Dnd_Drag_State)); + leave = calloc(1, sizeof(Dnd_Drag_State)); + pos = calloc(1, sizeof(Dnd_Drag_Pos)); + drop = calloc(1, sizeof(Dnd_Drop)); + if (!enter || !leave || !pos || !drop) return EINA_FALSE; +#ifdef HAVE_ELEMENTARY_WL2 + seatid = _wl_default_seat_id_get(obj); +#endif + enter->state_cb = enter_cb; + enter->state_data = enter_data; + leave->state_cb = leave_cb; + leave->state_data = leave_data; + pos->pos_cb = pos_cb; + pos->pos_data = pos_data; + drop->obj = obj; + drop->format = format; + drop->drop_cb = drop_cb; + drop->drop_data = drop_data; + drop->enter = enter; + drop->leave = leave; + drop->pos = pos; + + drop_list = efl_key_data_get(obj, "__drop_list"); + drop_list = eina_list_append(drop_list, drop); + efl_key_data_set(obj, "__drop_list", drop_list); + evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, + _drop_obj_del_cb, NULL); + efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_ENTER, + _dnd_drag_enter_leave_cb, enter); + efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_LEAVE, + _dnd_drag_enter_leave_cb, leave); + efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_POS, + _dnd_drag_pos_cb, pos); + efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_DROP, + _dnd_drop_cb, drop); + efl_selection_manager_drop_target_add(sel_man, obj, format, seatid); + + + return EINA_TRUE; +} + +EAPI Eina_Bool +elm_drop_target_del(Evas_Object *obj, Elm_Sel_Format format, + Elm_Drag_State enter_cb, void *enter_data, + Elm_Drag_State leave_cb, void *leave_data, + Elm_Drag_Pos pos_cb, void *pos_data, + Elm_Drop_Cb drop_cb, void *drop_data) +{ + Eo *sel_man = _selection_manager_get(obj); + int seatid = 1; + //Eina_List *l, *l2; + Eina_List *drop_list; + Dnd_Drop *drop; + +#ifdef HAVE_ELEMENTARY_WL2 + seatid = _wl_default_seat_id_get(obj); +#endif + + drop_list = efl_key_data_get(obj, "__drop_list"); + drop = eina_list_data_get(drop_list); + if (drop && + (drop->format == drop->format) && + (drop->enter->state_cb == enter_cb) && + (drop->enter->state_data == enter_data) && + (drop->leave->state_cb == leave_cb) && + (drop->leave->state_data == leave_data) && + (drop->pos->pos_cb == pos_cb) && + (drop->pos->pos_data == pos_data) && + (drop->drop_cb == drop_cb) && + (drop->drop_data == drop_data)) + { + drop_list = eina_list_remove(drop_list, drop); + efl_key_data_set(obj, "__drop_list", drop_list); + evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _drop_obj_del_cb); + efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_ENTER, + _dnd_drag_enter_leave_cb, drop->enter); + efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_LEAVE, + _dnd_drag_enter_leave_cb, drop->leave); + efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_POS, + _dnd_drag_pos_cb, drop->pos); + efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_DROP, + _dnd_drop_cb, drop); + free(drop->enter); + free(drop->leave); + free(drop->pos); + free(drop); + } + efl_selection_manager_drop_target_del(sel_man, obj, format, seatid); + + return EINA_TRUE; +} + +static Efl_Object * +_dnd_item_func(void *data, Efl_Canvas_Object *item, Eina_Position2D pos, Eina_Position2D *pos_ret) +{ + Elm_Xy_Item_Get_Cb item_get_cb = data; + Evas_Coord x, y; + Efl_Object *obj = NULL; + + x = y = 0; + if (item_get_cb) + obj = item_get_cb(item, pos.x, pos.y, &x, &y); + if (pos_ret) + { + pos_ret->x = x; + pos_ret->y = y; + } + + return obj; +} + +static void +_dnd_cont_drag_pos_cb(void *data, const Efl_Event *event) +{ + Dnd_Cont_Drag_Pos *pos = data; + Efl_Dnd_Drag_Pos *ddata = event->info; + Evas_Coord xret = 0, yret = 0; + + if (pos->item_get_cb) + { + Evas_Coord x, y; + evas_object_geometry_get(event->object, &x, &y, NULL, NULL); + pos->item_get_cb(event->object, ddata->pos.x + x, ddata->pos.y + y, + &xret, &yret); + } + if (pos->pos_cb) + pos->pos_cb(pos->pos_data, event->object, ddata->item, ddata->pos.x, ddata->pos.y, + xret, yret, ddata->action); +} + +static void +_dnd_cont_drop_cb(void *data, const Efl_Event *event) +{ + Dnd_Cont_Drop *drop = data; + Efl_Selection_Data *org_ddata = event->info; + Elm_Selection_Data ddata; + Evas_Coord xret = 0, yret = 0; + + ddata.x = org_ddata->pos.x; + ddata.y = org_ddata->pos.y; + ddata.format = org_ddata->format; + ddata.action = org_ddata->action; + ddata.data = calloc(1, org_ddata->data.len); + if (!ddata.data) return; + ddata.data = memcpy(ddata.data, org_ddata->data.mem, org_ddata->data.len); + ddata.len = org_ddata->data.len; + + if (drop->item_get_cb) + { + Evas_Coord x, y; + evas_object_geometry_get(event->object, &x, &y, NULL, NULL); + drop->item_get_cb(event->object, ddata.x + x, ddata.y + y, + &xret, &yret); + } + + if (drop->drop_cb) + drop->drop_cb(drop->drop_data, event->object, org_ddata->item, + &ddata, xret, yret); + free(ddata.data); +} + +static void +_cont_drop_free_data(Evas_Object *obj) +{ + Eina_List *cont_drop_list; + Dnd_Cont_Drop *drop; + + cont_drop_list = efl_key_data_get(obj, "__cont_drop_item"); + drop = eina_list_data_get(cont_drop_list); + if (drop) + { + efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_ENTER, + _dnd_drag_enter_leave_cb, drop->enter); + efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_LEAVE, + _dnd_drag_enter_leave_cb, drop->leave); + efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_POS, + _dnd_cont_drag_pos_cb, drop->pos); + efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_DROP, + _dnd_cont_drop_cb, drop); + free(drop->enter); + free(drop->leave); + free(drop->pos); + cont_drop_list = eina_list_remove(cont_drop_list, drop); + efl_key_data_set(obj, "__cont_drop_item", cont_drop_list); + free(drop); + } +} + +static void +_cont_drop_obj_del_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *info EINA_UNUSED) +{ + _cont_drop_free_data(obj); +} + +EAPI Eina_Bool +elm_drop_item_container_add(Evas_Object *obj, + Elm_Sel_Format format, + Elm_Xy_Item_Get_Cb item_get_cb, + Elm_Drag_State enter_cb, void *enter_data, + Elm_Drag_State leave_cb, void *leave_data, + Elm_Drag_Item_Container_Pos pos_cb, void *pos_data, + Elm_Drop_Item_Container_Cb drop_cb, void *drop_data) +{ + Eo *sel_man = _selection_manager_get(obj); + int seatid = 1; + Dnd_Drag_State *enter, *leave; + Dnd_Cont_Drag_Pos *pos; + Dnd_Cont_Drop *drop; + Eina_List *cont_drop_list; + + enter = calloc(1, sizeof(Dnd_Drag_State)); + leave = calloc(1, sizeof(Dnd_Drag_State)); + pos = calloc(1, sizeof(Dnd_Cont_Drag_Pos)); + drop = calloc(1, sizeof(Dnd_Cont_Drop)); + if (!enter || !leave || !pos || !drop) return EINA_FALSE; +#ifdef HAVE_ELEMENTARY_WL2 + seatid = _wl_default_seat_id_get(obj); +#endif + + enter->state_cb = enter_cb; + enter->state_data = enter_data; + leave->state_cb = leave_cb; + leave->state_data = leave_data; + pos->pos_cb = pos_cb; + pos->pos_data = pos_data; + pos->item_get_cb = item_get_cb; + drop->obj = obj; + drop->format = format; + drop->drop_cb = drop_cb; + drop->drop_data = drop_data; + drop->enter = enter; + drop->leave = leave; + drop->pos = pos; + + cont_drop_list = efl_key_data_get(obj, "__cont_drop_item"); + cont_drop_list = eina_list_append(cont_drop_list, drop); + efl_key_data_set(obj, "__cont_drop_item", cont_drop_list); + evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, + _cont_drop_obj_del_cb, NULL); + efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_ENTER, + _dnd_drag_enter_leave_cb, enter); + efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_LEAVE, + _dnd_drag_enter_leave_cb, leave); + efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_POS, + _dnd_cont_drag_pos_cb, pos); + efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_DROP, + _dnd_cont_drop_cb, drop); + efl_selection_manager_container_drop_item_add(sel_man, obj, format, + item_get_cb, _dnd_item_func, NULL, + seatid); + + return EINA_TRUE; +} + +EAPI Eina_Bool +elm_drop_item_container_del(Evas_Object *obj) +{ + Eo *sel_man = _selection_manager_get(obj); + int seatid = 1; + +#ifdef HAVE_ELEMENTARY_WL2 + seatid = _wl_default_seat_id_get(obj); +#endif + + _cont_drop_free_data(obj); + evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _cont_drop_obj_del_cb); + efl_selection_manager_container_drop_item_del(sel_man, obj, seatid); + + return EINA_TRUE; +} + +static void +_cont_drag_data_func(void *data, Efl_Object *obj, Efl_Selection_Format *format, + Eina_Rw_Slice *drag_data, Efl_Selection_Action *action) +{ + Item_Container_Drag_Info *di; + + di = data; + if (!di) return; + di->data_get_cb(obj, di->it, &di->user_info); + if (format) *format = di->user_info.format; + if (drag_data) + { + if (di->user_info.data) + { + drag_data->mem = (void *)di->user_info.data; + drag_data->len = strlen(di->user_info.data); + } + } + if (action) *action = di->user_info.action; +} + +static Eina_List * +_cont_drag_icon_list_create(void *data, Efl_Object *obj EINA_UNUSED) +{ + Item_Container_Drag_Info *di; + + di = data; + return di->user_info.icons; +} + +static Efl_Object * +_cont_drag_icon_create(void *data, Efl_Object *win, Efl_Object *drag_obj EINA_UNUSED, Eina_Position2D *pos_ret) +{ + Item_Container_Drag_Info *di; + Elm_Object_Item *it = NULL; + + di = data; + if (!di) return NULL; + it = di->user_info.createicon(di->user_info.createdata, win, &pos_ret->x, &pos_ret->y); + di->it = it; + return it; +} + +static Efl_Object * +_cont_drag_item_func(void *data, Efl_Canvas_Object *item, Eina_Position2D pos, Eina_Position2D *pos_ret) +{ + Item_Container_Drag_Info *di = data; + Evas_Coord x, y; + Efl_Object *obj = NULL; + + x = y = 0; + if (di->item_get_cb) + obj = di->item_get_cb(item, pos.x, pos.y, &x, &y); + if (pos_ret) + { + pos_ret->x = x; + pos_ret->y = y; + } + di->it = obj; + + return obj; +} + +static void +_cont_drag_free_data(Evas_Object *obj) +{ + Eina_List *di_list; + Item_Container_Drag_Info *di; + + di_list = efl_key_data_get(obj, "__cont_drag_item"); + di = eina_list_data_get(di_list); + di_list = eina_list_remove(di_list, di); + efl_key_data_set(obj, "__cont_drag_item", di_list); + free(di); +} + +static void +_cont_drag_obj_del_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event EINA_UNUSED) +{ + _cont_drag_free_data(obj); +} + +EAPI Eina_Bool +elm_drag_item_container_add(Evas_Object *obj, double anim_tm, double tm_to_drag, + Elm_Xy_Item_Get_Cb item_get_cb, Elm_Item_Container_Data_Get_Cb data_get_cb) +{ + Eo *sel_man = _selection_manager_get(obj); + int seatid = 1; + Eina_List *di_list; + Item_Container_Drag_Info *di; + +#ifdef HAVE_ELEMENTARY_WL2 + seatid = _wl_default_seat_id_get(obj); +#endif + + di = calloc(1, sizeof(Item_Container_Drag_Info)); + if (!di) return EINA_FALSE; + di->data_get_cb = data_get_cb; + di->item_get_cb = item_get_cb; + di_list = efl_key_data_get(obj, "__cont_drag_item"); + di_list = eina_list_append(di_list, di); + efl_key_data_set(obj, "__cont_drag_item", di_list); + evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _cont_drag_obj_del_cb, NULL); + efl_selection_manager_container_drag_item_add(sel_man, obj, anim_tm, tm_to_drag, + di, _cont_drag_data_func, NULL, + di, _cont_drag_item_func, NULL, + di, _cont_drag_icon_create, NULL, + di, _cont_drag_icon_list_create, NULL, + seatid); + return EINA_TRUE; +} + +EAPI Eina_Bool +elm_drag_item_container_del(Evas_Object *obj) +{ + Eo *sel_man = _selection_manager_get(obj); + int seatid = 1; + +#ifdef HAVE_ELEMENTARY_WL2 + seatid = _wl_default_seat_id_get(obj); +#endif + + _cont_drag_free_data(obj); + evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _cont_drag_obj_del_cb); + efl_selection_manager_container_drag_item_del(sel_man, obj, seatid); + + return EINA_TRUE; +} + #include "efl_ui_dnd.eo.c" #include "efl_ui_dnd_container.eo.c" -- 2.7.4