From e88bbaa1e314751e5c1a04dec7f1f179188428ae 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 +++ src/lib/elementary/elm_cnp.c | 5851 -------------------- 5 files changed, 963 insertions(+), 5898 deletions(-) delete mode 100644 src/lib/elementary/elm_cnp.c diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am index 75204582fe..d0af9ad567 100644 --- a/src/Makefile_Elementary.am +++ b/src/Makefile_Elementary.am @@ -618,7 +618,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 9f086e340e..00cfe13e1b 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 91cc4a6149..bcb79aa13d 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 731229d121..ae27c53bd6 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" diff --git a/src/lib/elementary/elm_cnp.c b/src/lib/elementary/elm_cnp.c deleted file mode 100644 index e7ac5cb625..0000000000 --- a/src/lib/elementary/elm_cnp.c +++ /dev/null @@ -1,5851 +0,0 @@ -#ifdef HAVE_CONFIG_H -# include "elementary_config.h" -#endif -#include -#include -#include "elm_priv.h" -#ifdef HAVE_MMAN_H -# include -#endif - -//#define DEBUGON 1 -#ifdef DEBUGON -# define cnp_debug(fmt, args...) fprintf(stderr, __FILE__":%s/%d : " fmt , __FUNCTION__, __LINE__, ##args) -#else -# define cnp_debug(x...) do { } while (0) -#endif - -#define ARRAYINIT(foo) [foo] = - -EAPI int ELM_CNP_EVENT_SELECTION_CHANGED = -1; - -// common stuff -enum -{ - CNP_ATOM_TARGETS = 0, - CNP_ATOM_ATOM, - CNP_ATOM_LISTING_ATOMS = CNP_ATOM_ATOM, - CNP_ATOM_text_urilist, - CNP_ATOM_text_x_vcard, - CNP_ATOM_image_png, - CNP_ATOM_image_jpeg, - CNP_ATOM_image_bmp, - CNP_ATOM_image_gif, - CNP_ATOM_image_tiff, - CNP_ATOM_image_svg, - CNP_ATOM_image_xpm, - CNP_ATOM_image_tga, - CNP_ATOM_image_ppm, - CNP_ATOM_XELM, -// CNP_ATOM_text_html_utf8, -// CNP_ATOM_text_html, - CNP_ATOM_UTF8STRING, - CNP_ATOM_STRING, - CNP_ATOM_COMPOUND_TEXT, - CNP_ATOM_TEXT, - CNP_ATOM_text_plain_utf8, - CNP_ATOM_text_plain, - - CNP_N_ATOMS, -}; - -typedef struct _Tmp_Info Tmp_Info; -typedef struct _Saved_Type Saved_Type; -typedef struct _Cnp_Escape Cnp_Escape; -typedef struct _Dropable Dropable; -typedef struct _Dropable_Cbs Dropable_Cbs; -static Eina_Bool doaccept = EINA_FALSE; - -struct _Tmp_Info -{ - char *filename; - void *map; - int fd; - int len; -}; - -struct _Saved_Type -{ - const char **types; - char *imgfile; - int ntypes; - int x, y; - Eina_Bool textreq: 1; -}; - -struct _Cnp_Escape -{ - const char *escape; - const char *value; -}; - -struct _Dropable_Cbs -{ - EINA_INLIST; - Elm_Sel_Format types; - Elm_Drag_State entercb; - Elm_Drag_State leavecb; - Elm_Drag_Pos poscb; - Elm_Drop_Cb dropcb; - void *enterdata; - void *leavedata; - void *posdata; - void *dropdata; -}; - -struct _Dropable -{ - Evas_Object *obj; - /* FIXME: Cache window */ - Eina_Inlist *cbs_list; /* List of Dropable_Cbs * */ - struct { - Evas_Coord x, y; - Eina_Bool in : 1; - const char *type; - Elm_Sel_Format format; - } last; -}; - -struct _Item_Container_Drop_Info -{ /* Info kept for containers to support drop */ - Evas_Object *obj; - Elm_Xy_Item_Get_Cb itemgetcb; - Elm_Drop_Item_Container_Cb dropcb; - Elm_Drag_Item_Container_Pos poscb; -}; -typedef struct _Item_Container_Drop_Info Item_Container_Drop_Info; - -struct _Anim_Icon -{ - int start_x; - int start_y; - int start_w; - int start_h; - Evas_Object *o; -}; -typedef struct _Anim_Icon Anim_Icon; - -struct _Item_Container_Drag_Info -{ /* Info kept for containers to support drag */ - Evas_Object *obj; - Ecore_Timer *tm; /* When this expires, start drag */ - double anim_tm; /* Time period to set tm */ - double tm_to_drag; /* Time period to set tm */ - Elm_Xy_Item_Get_Cb itemgetcb; - Elm_Item_Container_Data_Get_Cb data_get; - - Evas_Coord x_down; /* Mouse down x cord when drag starts */ - Evas_Coord y_down; /* Mouse down y cord when drag starts */ - - /* Some extra information needed to impl default anim */ - Evas *e; - Eina_List *icons; /* List of icons to animate (Anim_Icon) */ - int final_icon_w; /* We need the w and h of the final icon for the animation */ - int final_icon_h; - Ecore_Animator *ea; - - Elm_Drag_User_Info user_info; -}; -typedef struct _Item_Container_Drag_Info Item_Container_Drag_Info; - -typedef struct _Cnp_Atom Cnp_Atom; - -static int _elm_cnp_init_count = 0; -/* Stringshared, so I can just compare pointers later */ -static const char *text_uri; - -/* Hash table type->Elm_Sel_Format */ -static Eina_Hash *_types_hash = NULL; - -/* Data for DND in progress */ -static Saved_Type savedtypes = { NULL, NULL, 0, 0, 0, EINA_FALSE }; - -/* Drag & Drop functions */ -/* FIXME: Way too many globals */ -static Eina_List *drops = NULL; -static Evas_Object *dragwin = NULL; -static int dragwin_x_start, dragwin_y_start; -static int dragwin_x_end, dragwin_y_end; -static int _dragx = 0, _dragy = 0; -static Ecore_Event_Handler *handler_pos = NULL; -static Ecore_Event_Handler *handler_drop = NULL; -static Ecore_Event_Handler *handler_enter = NULL; -static Ecore_Event_Handler *handler_leave = NULL; -#ifdef HAVE_ELEMENTARY_X -static Ecore_Event_Handler *handler_status = NULL; -static Ecore_Event_Handler *handler_up = NULL; -#endif - -/* TODO BUG: should NEVER have these as globals! They should be per context (window). */ -static Elm_Drag_Pos dragposcb = NULL; -static Elm_Drag_Accept dragacceptcb = NULL; -static Elm_Drag_State dragdonecb = NULL; -static void *dragposdata = NULL; -static void *dragacceptdata = NULL; -static void *dragdonedata = NULL; -static Evas_Object *dragwidget = NULL; -static Elm_Xdnd_Action dragaction = ELM_XDND_ACTION_UNKNOWN; - -static Eina_List *cont_drop_tg = NULL; /* List of Item_Container_Drop_Info */ -static Eina_List *cont_drag_tg = NULL; /* List of Item_Container_Drag_Info */ - -static void _cont_obj_mouse_up( void *data, Evas *e, Evas_Object *obj, void *event_info); -static void _cont_obj_mouse_move( void *data, Evas *e, Evas_Object *obj, void *event_info); -static void _all_drop_targets_cbs_del(void *data, Evas *e, Evas_Object *obj, void *info); -static Eina_Bool _elm_cnp_shutdown(void); -static Eina_Bool _local_elm_drop_target_del(Evas_Object *obj, Elm_Sel_Format format, - Elm_Drag_State entercb, void *enterdata, - Elm_Drag_State leavecb, void *leavedata, - Elm_Drag_Pos poscb, void *posdata, - Elm_Drop_Cb dropcb, void *dropdata); - -static Tmp_Info *_tempfile_new (int size); -static int _tmpinfo_free (Tmp_Info *tmp); - -static Eina_Bool _local_elm_cnp_selection_get(const Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata); -static Eina_Bool _local_elm_object_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type selection); -static Eina_Bool _local_elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, const void *selbuf, size_t buflen); -#ifdef HAVE_ELEMENTARY_X -static Ecore_X_Window _x11_elm_widget_xwin_get(const Evas_Object *obj); - -typedef struct _X11_Cnp_Selection X11_Cnp_Selection; - -typedef Eina_Bool (*X11_Converter_Fn_Cb) (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize); -typedef int (*X11_Response_Handler_Cb) (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *); -typedef Eina_Bool (*X11_Data_Preparer_Cb) (Ecore_X_Event_Selection_Notify *, Elm_Selection_Data *, Tmp_Info **); - -static void _x11_sel_obj_del (void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED); -static void _x11_sel_obj_del2 (void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED); -static Eina_Bool _x11_selection_clear (void *udata EINA_UNUSED, int type, void *event); -static Eina_Bool _x11_selection_notify (void *udata EINA_UNUSED, int type, void *event); -static Eina_Bool _x11_targets_converter (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize); -static Eina_Bool _x11_text_converter (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize); -static Eina_Bool _x11_general_converter (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize); -static Eina_Bool _x11_image_converter (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize); -static Eina_Bool _x11_vcard_send (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize); -static Eina_Bool _x11_is_uri_type_data (X11_Cnp_Selection *sel EINA_UNUSED, Ecore_X_Event_Selection_Notify *notify); -static Eina_Bool _x11_notify_handler_targets (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify); -static Eina_Bool _x11_data_preparer_text (Ecore_X_Event_Selection_Notify *notify, Elm_Selection_Data *ddata, Tmp_Info **tmp_info); -static Eina_Bool _x11_data_preparer_markup (Ecore_X_Event_Selection_Notify *notify, Elm_Selection_Data *ddata, Tmp_Info **tmp_info); -static Eina_Bool _x11_data_preparer_image (Ecore_X_Event_Selection_Notify *notify, Elm_Selection_Data *ddata, Tmp_Info **tmp_info); -static Eina_Bool _x11_data_preparer_uri (Ecore_X_Event_Selection_Notify *notify, Elm_Selection_Data *ddata, Tmp_Info **tmp_info); -//static int _x11_notify_handler_html (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify); -static Eina_Bool _x11_data_preparer_vcard (Ecore_X_Event_Selection_Notify *notify, Elm_Selection_Data *ddata, Tmp_Info **tmp_info); -static Eina_Bool _x11_dnd_enter (void *data EINA_UNUSED, int etype EINA_UNUSED, void *ev); -static Eina_Bool _x11_dnd_drop (void *data EINA_UNUSED, int etype EINA_UNUSED, void *ev); -static Eina_Bool _x11_dnd_position (void *data EINA_UNUSED, int etype EINA_UNUSED, void *ev); -static Eina_Bool _x11_dnd_status (void *data EINA_UNUSED, int etype EINA_UNUSED, void *ev); -static Eina_Bool _x11_dnd_leave (void *data EINA_UNUSED, int etype EINA_UNUSED, void *ev); -static Eina_Bool _x11_drag_mouse_up (void *data, int etype EINA_UNUSED, void *event); -static void _x11_drag_move (void *data EINA_UNUSED, Ecore_X_Xdnd_Position *pos); - -static Eina_Bool _x11_elm_cnp_init (void); -static Eina_Bool _x11_elm_cnp_selection_set (Ecore_X_Window xwin, Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, const void *selbuf, size_t buflen); -static void _x11_elm_cnp_selection_loss_callback_set(Evas_Object *obj EINA_UNUSED, Elm_Sel_Type selection, Elm_Selection_Loss_Cb func, const void *data); -static Eina_Bool _x11_elm_object_cnp_selection_clear (Evas_Object *obj, Elm_Sel_Type selection); -static Eina_Bool _x11_elm_cnp_selection_get (Ecore_X_Window xwin, const Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata); -static Eina_Bool _x11_elm_drop_target_add (Evas_Object *obj, Elm_Sel_Format format, - Elm_Drag_State entercb, void *enterdata, - Elm_Drag_State leavecb, void *leavedata, - Elm_Drag_Pos poscb, void *posdata, - Elm_Drop_Cb dropcb, void *dropdata); -static Eina_Bool _x11_elm_drop_target_del (Evas_Object *obj, Elm_Sel_Format format, - Elm_Drag_State entercb, void *enterdata, - Elm_Drag_State leavecb, void *leavedata, - Elm_Drag_Pos poscb, void *posdata, - Elm_Drop_Cb dropcb, void *dropdata); -static Eina_Bool _x11_elm_selection_selection_has_owner (Evas_Object *obj EINA_UNUSED); - -#endif - -#ifdef HAVE_ELEMENTARY_WL2 -typedef struct _Wl_Cnp_Selection Wl_Cnp_Selection; - -typedef Eina_Bool (*Wl_Converter_Fn_Cb) (char *target, Wl_Cnp_Selection *sel, void *data, int size, void **data_ret, int *size_ret); -static Eina_Bool _wl_targets_converter(char *target, Wl_Cnp_Selection *sel, void *data, int size, void **data_ret, int *size_ret); -static Eina_Bool _wl_general_converter(char *target, Wl_Cnp_Selection *sel, void *data, int size, void **data_ret, int *size_ret); -static Eina_Bool _wl_text_converter(char *target, Wl_Cnp_Selection *sel, void *data, int size, void **data_ret, int *size_ret); - -typedef Eina_Bool (*Wl_Data_Preparer_Cb) (Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info); -static Eina_Bool _wl_data_preparer_markup(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info); -static Eina_Bool _wl_data_preparer_uri(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info); -static Eina_Bool _wl_data_preparer_vcard(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info); -static Eina_Bool _wl_data_preparer_image(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info); -static Eina_Bool _wl_data_preparer_text(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info); -#endif - -struct _Cnp_Atom -{ - const char *name; - Elm_Sel_Format formats; -#ifdef HAVE_ELEMENTARY_X - /* Called by ecore to do conversion */ - X11_Converter_Fn_Cb x_converter; - X11_Data_Preparer_Cb x_data_preparer; - /* Atom */ - Ecore_X_Atom x_atom; -#endif -#ifdef HAVE_ELEMENTARY_WL2 - Wl_Converter_Fn_Cb wl_converter; - Wl_Data_Preparer_Cb wl_data_preparer; -#endif - - void *_term; -}; - -static Eina_List * -_dropable_list_geom_find(Evas *evas, Evas_Coord px, Evas_Coord py) -{ - Eina_List *itr, *top_objects_list = NULL, *dropable_list = NULL; - Evas_Object *top_obj; - Dropable *dropable = NULL; - - if (!drops) return NULL; - - /* We retrieve the (non-smart) objects pointed by (px, py) */ - top_objects_list = evas_tree_objects_at_xy_get(evas, NULL, px, py); - /* We walk on this list from the last because if the list contains more than one - * element, all but the last will repeat events. The last one can repeat events - * or not. Anyway, this last one is the first that has to be taken into account - * for the determination of the drop target. - */ - EINA_LIST_REVERSE_FOREACH(top_objects_list, itr, top_obj) - { - Evas_Object *object = top_obj; - /* We search for the dropable data into the object. If not found, we search into its parent. - * For example, if a button is a drop target, the first object will be an (internal) image. - * The drop target is attached to the button, i.e to image's parent. That's why we need to - * walk on the parents until NULL. - * If we find this dropable data, we found our drop target. - */ - while (object) - { - dropable = efl_key_data_get(object, "__elm_dropable"); - if (dropable) - { - Eina_Bool exist = EINA_FALSE; - Eina_List *l; - Dropable *d = NULL; - EINA_LIST_FOREACH(dropable_list, l, d) - { - if (d == dropable) - { - exist = EINA_TRUE; - break; - } - } - if (!exist) - dropable_list = eina_list_append(dropable_list, dropable); - object = evas_object_smart_parent_get(object); - if (dropable) - cnp_debug("Drop target %p of type %s found\n", - dropable->obj, efl_class_name_get(efl_class_get(dropable->obj))); - } - else - object = evas_object_smart_parent_get(object); - } - } - eina_list_free(top_objects_list); - return dropable_list; -} - -static void -_dropable_coords_adjust(Dropable *dropable, Evas_Coord *x, Evas_Coord *y) -{ - Ecore_Evas *ee; - Evas *evas = evas_object_evas_get(dropable->obj); - int ex = 0, ey = 0, ew = 0, eh = 0; - Evas_Object *win; - - ee = ecore_evas_ecore_evas_get(evas); - ecore_evas_geometry_get(ee, &ex, &ey, &ew, &eh); - *x = *x - ex; - *y = *y - ey; - - /* For Wayland, frame coords have to be subtracted. */ - Evas_Coord fx, fy; - evas_output_framespace_get(evas, &fx, &fy, NULL, NULL); - if (fx || fy) cnp_debug("evas frame fx %d fy %d\n", fx, fy); - *x = *x - fx; - *y = *y - fy; - - if (elm_widget_is(dropable->obj)) - { - win = elm_widget_top_get(dropable->obj); - if (win && efl_isa(win, EFL_UI_WIN_CLASS)) - { - Evas_Coord x2, y2; - int rot = elm_win_rotation_get(win); - switch (rot) - { - case 90: - x2 = ew - *y; - y2 = *x; - break; - case 180: - x2 = ew - *x; - y2 = eh - *y; - break; - case 270: - x2 = *y; - y2 = eh - *x; - break; - default: - x2 = *x; - y2 = *y; - break; - } - cnp_debug("rotation %d, w %d, h %d - x:%d->%d, y:%d->%d\n", - rot, ew, eh, *x, x2, *y, y2); - *x = x2; - *y = y2; - } - } -} - -static Elm_Sel_Format -_dnd_types_to_format(const char **types, int ntypes) -{ - Elm_Sel_Format ret_type = 0; - int i; - for (i = 0; i < ntypes; i++) - { - Cnp_Atom *atom = eina_hash_find(_types_hash, types[i]); - if (atom) ret_type |= atom->formats; - } - return ret_type; -} - -static Eina_Bool -_drag_cancel_animate(void *data, double pos) -{ /* Animation to "move back" drag-window */ - if (pos >= 0.99) - { -#ifdef HAVE_ELEMENTARY_X - Ecore_X_Window xdragwin = _x11_elm_widget_xwin_get(data); - ecore_x_window_ignore_set(xdragwin, 0); -#endif - evas_object_del(data); - return ECORE_CALLBACK_CANCEL; - } - else - { - int x, y; - x = dragwin_x_end - (pos * (dragwin_x_end - dragwin_x_start)); - y = dragwin_y_end - (pos * (dragwin_y_end - dragwin_y_start)); - evas_object_move(data, x, y); - } - - return ECORE_CALLBACK_RENEW; -} - -static void -_all_drop_targets_cbs_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *info EINA_UNUSED) -{ - Dropable *dropable = NULL; - dropable = efl_key_data_get(obj, "__elm_dropable"); - if (dropable) - { - Dropable_Cbs *cbs; - while (dropable->cbs_list) - { - cbs = EINA_INLIST_CONTAINER_GET(dropable->cbs_list, Dropable_Cbs); - elm_drop_target_del(obj, cbs->types, - cbs->entercb, cbs->enterdata, cbs->leavecb, cbs->leavedata, - cbs->poscb, cbs->posdata, cbs->dropcb, cbs->dropdata); - // If elm_drop_target_del() happened to delete dropabale, then - // re-fetch it each loop to make sure it didn't - dropable = efl_key_data_get(obj, "__elm_dropable"); - if (!dropable) break; - } - } -} - -static Cnp_Atom _atoms[CNP_N_ATOMS] = { - ARRAYINIT(CNP_ATOM_TARGETS) { - .name = "TARGETS", - .formats = ELM_SEL_FORMAT_TARGETS, -#ifdef HAVE_ELEMENTARY_X - .x_converter = _x11_targets_converter, - -#endif -#ifdef HAVE_ELEMENTARY_WL2 - .wl_converter = _wl_targets_converter, -#endif - }, - ARRAYINIT(CNP_ATOM_ATOM) { - .name = "ATOM", // for opera browser - .formats = ELM_SEL_FORMAT_TARGETS, -#ifdef HAVE_ELEMENTARY_X - .x_converter = _x11_targets_converter, -#endif -#ifdef HAVE_ELEMENTARY_WL2 - .wl_converter = _wl_targets_converter, -#endif - }, - ARRAYINIT(CNP_ATOM_XELM) { - .name = "application/x-elementary-markup", - .formats = ELM_SEL_FORMAT_MARKUP, -#ifdef HAVE_ELEMENTARY_X - .x_converter = _x11_general_converter, - .x_data_preparer = _x11_data_preparer_markup, -#endif -#ifdef HAVE_ELEMENTARY_WL2 - .wl_converter = _wl_general_converter, - .wl_data_preparer = _wl_data_preparer_markup, -#endif - }, - ARRAYINIT(CNP_ATOM_text_urilist) { - .name = "text/uri-list", - .formats = ELM_SEL_FORMAT_IMAGE, -#ifdef HAVE_ELEMENTARY_X - .x_converter = _x11_general_converter, - .x_data_preparer = _x11_data_preparer_uri, -#endif -#ifdef HAVE_ELEMENTARY_WL2 - .wl_converter = _wl_general_converter, - .wl_data_preparer = _wl_data_preparer_uri, -#endif - }, - ARRAYINIT(CNP_ATOM_text_x_vcard) { - .name = "text/x-vcard", - .formats = ELM_SEL_FORMAT_VCARD, -#ifdef HAVE_ELEMENTARY_X - .x_converter = _x11_vcard_send, - .x_data_preparer = _x11_data_preparer_vcard, -#endif -#ifdef HAVE_ELEMENTARY_WL2 - .wl_data_preparer = _wl_data_preparer_vcard, -#endif - }, - ARRAYINIT(CNP_ATOM_image_png) { - .name = "image/png", - .formats = ELM_SEL_FORMAT_IMAGE, -#ifdef HAVE_ELEMENTARY_X - .x_converter = _x11_image_converter, - .x_data_preparer = _x11_data_preparer_image, -#endif -#ifdef HAVE_ELEMENTARY_WL2 - .wl_data_preparer = _wl_data_preparer_image, -#endif - }, - ARRAYINIT(CNP_ATOM_image_jpeg) { - .name = "image/jpeg", - .formats = ELM_SEL_FORMAT_IMAGE, -#ifdef HAVE_ELEMENTARY_X - .x_converter = _x11_image_converter, - .x_data_preparer = _x11_data_preparer_image, -#endif -#ifdef HAVE_ELEMENTARY_WL2 - .wl_data_preparer = _wl_data_preparer_image, -#endif - }, - ARRAYINIT(CNP_ATOM_image_bmp) { - .name = "image/x-ms-bmp", - .formats = ELM_SEL_FORMAT_IMAGE, -#ifdef HAVE_ELEMENTARY_X - .x_converter = _x11_image_converter, - .x_data_preparer = _x11_data_preparer_image, -#endif -#ifdef HAVE_ELEMENTARY_WL2 - .wl_data_preparer = _wl_data_preparer_image, -#endif - }, - ARRAYINIT(CNP_ATOM_image_gif) { - .name = "image/gif", - .formats = ELM_SEL_FORMAT_IMAGE, -#ifdef HAVE_ELEMENTARY_X - .x_converter = _x11_image_converter, - .x_data_preparer = _x11_data_preparer_image, -#endif -#ifdef HAVE_ELEMENTARY_WL2 - .wl_data_preparer = _wl_data_preparer_image, -#endif - }, - ARRAYINIT(CNP_ATOM_image_tiff) { - .name = "image/tiff", - .formats = ELM_SEL_FORMAT_IMAGE, -#ifdef HAVE_ELEMENTARY_X - .x_converter = _x11_image_converter, - .x_data_preparer = _x11_data_preparer_image, -#endif -#ifdef HAVE_ELEMENTARY_WL2 - .wl_data_preparer = _wl_data_preparer_image, -#endif - }, - ARRAYINIT(CNP_ATOM_image_svg) { - .name = "image/svg+xml", - .formats = ELM_SEL_FORMAT_IMAGE, -#ifdef HAVE_ELEMENTARY_X - .x_converter = _x11_image_converter, - .x_data_preparer = _x11_data_preparer_image, -#endif -#ifdef HAVE_ELEMENTARY_WL2 - .wl_data_preparer = _wl_data_preparer_image, -#endif - }, - ARRAYINIT(CNP_ATOM_image_xpm) { - .name = "image/x-xpixmap", - .formats = ELM_SEL_FORMAT_IMAGE, -#ifdef HAVE_ELEMENTARY_X - .x_converter = _x11_image_converter, - .x_data_preparer = _x11_data_preparer_image, -#endif -#ifdef HAVE_ELEMENTARY_WL2 - .wl_data_preparer = _wl_data_preparer_image, -#endif - }, - ARRAYINIT(CNP_ATOM_image_tga) { - .name = "image/x-tga", - .formats = ELM_SEL_FORMAT_IMAGE, -#ifdef HAVE_ELEMENTARY_X - .x_converter = _x11_image_converter, - .x_data_preparer = _x11_data_preparer_image, -#endif -#ifdef HAVE_ELEMENTARY_WL2 - .wl_data_preparer = _wl_data_preparer_image, -#endif - }, - ARRAYINIT(CNP_ATOM_image_ppm) { - .name = "image/x-portable-pixmap", - .formats = ELM_SEL_FORMAT_IMAGE, -#ifdef HAVE_ELEMENTARY_X - .x_converter = _x11_image_converter, - .x_data_preparer = _x11_data_preparer_image, -#endif -#ifdef HAVE_ELEMENTARY_WL2 - .wl_data_preparer = _wl_data_preparer_image, -#endif - }, -/* - ARRAYINIT(CNP_ATOM_text_html_utf8) { - .name = "text/html;charset=utf-8", - .formats = ELM_SEL_FORMAT_HTML, -#ifdef HAVE_ELEMENTARY_X - .x_converter = _x11_general_converter, - .x_notify = _x11_notify_handler_html, -#endif -#ifdef HAVE_ELEMENTARY_WL2 - .wl_converter = _wl_general_converter, - .wl_data_preparer = _wl_data_preparer_handler_html, -#endif - - }, - ARRAYINIT(CNP_ATOM_text_html) { - .name = "text/html", - .formats = ELM_SEL_FORMAT_HTML, -#ifdef HAVE_ELEMENTARY_X - .x_converter = _x11_general_converter, - .x_notify = _x11_notify_handler_html, -#endif -#ifdef HAVE_ELEMENTARY_WL2 - .wl_converter = _wl_general_converter, - .wl_data_preparer = _wl_data_preparer_handler_html, -#endif - }, - */ - ARRAYINIT(CNP_ATOM_UTF8STRING) { - .name = "UTF8_STRING", - .formats = ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML, -#ifdef HAVE_ELEMENTARY_X - .x_converter = _x11_text_converter, - .x_data_preparer = _x11_data_preparer_text, -#endif -#ifdef HAVE_ELEMENTARY_WL2 - .wl_converter = _wl_text_converter, - .wl_data_preparer = _wl_data_preparer_text, -#endif - }, - ARRAYINIT(CNP_ATOM_STRING) { - .name = "STRING", - .formats = ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML, -#ifdef HAVE_ELEMENTARY_X - .x_converter = _x11_text_converter, - .x_data_preparer = _x11_data_preparer_text, -#endif -#ifdef HAVE_ELEMENTARY_WL2 - .wl_converter = _wl_text_converter, - .wl_data_preparer = _wl_data_preparer_text, -#endif - }, - ARRAYINIT(CNP_ATOM_COMPOUND_TEXT) { - .name = "COMPOUND_TEXT", - .formats = ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML, -#ifdef HAVE_ELEMENTARY_X - .x_converter = _x11_text_converter, - .x_data_preparer = _x11_data_preparer_text, -#endif -#ifdef HAVE_ELEMENTARY_WL2 - .wl_converter = _wl_text_converter, - .wl_data_preparer = _wl_data_preparer_text, -#endif - }, - ARRAYINIT(CNP_ATOM_TEXT) { - .name = "TEXT", - .formats = ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML, -#ifdef HAVE_ELEMENTARY_X - .x_converter = _x11_text_converter, - .x_data_preparer = _x11_data_preparer_text, -#endif -#ifdef HAVE_ELEMENTARY_WL2 - .wl_converter = _wl_text_converter, - .wl_data_preparer = _wl_data_preparer_text, -#endif - }, - ARRAYINIT(CNP_ATOM_text_plain_utf8) { - .name = "text/plain;charset=utf-8", - .formats = ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML, -#ifdef HAVE_ELEMENTARY_X - .x_converter = _x11_text_converter, - .x_data_preparer = _x11_data_preparer_text, -#endif -#ifdef HAVE_ELEMENTARY_WL2 - .wl_converter = _wl_text_converter, - .wl_data_preparer = _wl_data_preparer_text, -#endif - }, - ARRAYINIT(CNP_ATOM_text_plain) { - .name = "text/plain", - .formats = ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML, -#ifdef HAVE_ELEMENTARY_X - .x_converter = _x11_text_converter, - .x_data_preparer = _x11_data_preparer_text, -#endif -#ifdef HAVE_ELEMENTARY_WL2 - .wl_converter = _wl_text_converter, - .wl_data_preparer = _wl_data_preparer_text, -#endif - }, -}; - -// x11 specific stuff -//////////////////////////////////////////////////////////////////////////// -#ifdef HAVE_ELEMENTARY_X -#define ARRAYINIT(foo) [foo] = -struct _X11_Cnp_Selection -{ - const char *debug; - Evas_Object *widget; - char *selbuf; - Evas_Object *requestwidget; - void *udata; - Elm_Sel_Format requestformat; - Elm_Drop_Cb datacb; - Eina_Bool (*set) (Ecore_X_Window, const void *data, int size); - Eina_Bool (*clear) (void); - void (*request) (Ecore_X_Window, const char *target); - Elm_Selection_Loss_Cb loss_cb; - void *loss_data; - - Elm_Sel_Format format; - Ecore_X_Selection ecore_sel; - Ecore_X_Window xwin; - Elm_Xdnd_Action action; - - Eina_Bool active : 1; -}; - -static X11_Cnp_Selection _x11_selections[ELM_SEL_TYPE_CLIPBOARD + 1] = { - ARRAYINIT(ELM_SEL_TYPE_PRIMARY) { - .debug = "Primary", - .ecore_sel = ECORE_X_SELECTION_PRIMARY, - .set = ecore_x_selection_primary_set, - .clear = ecore_x_selection_primary_clear, - .request = ecore_x_selection_primary_request, - }, - ARRAYINIT(ELM_SEL_TYPE_SECONDARY) { - .debug = "Secondary", - .ecore_sel = ECORE_X_SELECTION_SECONDARY, - .set = ecore_x_selection_secondary_set, - .clear = ecore_x_selection_secondary_clear, - .request = ecore_x_selection_secondary_request, - }, - ARRAYINIT(ELM_SEL_TYPE_XDND) { - .debug = "XDnD", - .ecore_sel = ECORE_X_SELECTION_XDND, - .request = ecore_x_selection_xdnd_request, - }, - ARRAYINIT(ELM_SEL_TYPE_CLIPBOARD) { - .debug = "Clipboard", - .ecore_sel = ECORE_X_SELECTION_CLIPBOARD, - .set = ecore_x_selection_clipboard_set, - .clear = ecore_x_selection_clipboard_clear, - .request = ecore_x_selection_clipboard_request, - }, -}; - -static void -_x11_sel_obj_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) -{ - X11_Cnp_Selection *sel = data; - if (sel->widget == obj) - { - sel->loss_cb = NULL; - sel->loss_data = NULL; - sel->widget = NULL; - } - if (dragwidget == obj) dragwidget = NULL; -} - -static void -_x11_sel_obj_del2(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) -{ - X11_Cnp_Selection *sel = data; - if (sel->requestwidget == obj) sel->requestwidget = NULL; -} - -static Eina_Bool -_x11_selection_clear(void *udata EINA_UNUSED, int type EINA_UNUSED, void *event) -{ - Ecore_X_Event_Selection_Clear *ev = event; - X11_Cnp_Selection *sel; - unsigned int i; - - _x11_elm_cnp_init(); - for (i = ELM_SEL_TYPE_PRIMARY; i <= ELM_SEL_TYPE_CLIPBOARD; i++) - { - if (_x11_selections[i].ecore_sel == ev->selection) break; - } - cnp_debug("selection %d clear\n", i); - /* Not me... Don't care */ - if (i > ELM_SEL_TYPE_CLIPBOARD) return ECORE_CALLBACK_PASS_ON; - - sel = _x11_selections + i; - if (sel->loss_cb) sel->loss_cb(sel->loss_data, i); - if (sel->widget) - evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL, - _x11_sel_obj_del, sel); - if (sel->requestwidget) - evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL, - _x11_sel_obj_del2, sel); - sel->widget = NULL; - sel->requestwidget = NULL; - sel->loss_cb = NULL; - sel->loss_data = NULL; - - sel->active = EINA_FALSE; - ELM_SAFE_FREE(sel->selbuf, free); - return ECORE_CALLBACK_PASS_ON; -} - -static Eina_Bool -_x11_fixes_selection_notify(void *d EINA_UNUSED, int t EINA_UNUSED, void *event) -{ - Elm_Cnp_Event_Selection_Changed *e; - Ecore_X_Event_Fixes_Selection_Notify *ev = event; - Elm_Sel_Type type; - X11_Cnp_Selection *sel; - - switch (ev->selection) - { - case ECORE_X_SELECTION_CLIPBOARD: - type = ELM_SEL_TYPE_CLIPBOARD; - break; - case ECORE_X_SELECTION_PRIMARY: - type = ELM_SEL_TYPE_PRIMARY; - break; - default: return ECORE_CALLBACK_RENEW; - } - sel = _x11_selections + type; - if (sel->active && (sel->xwin != ev->owner)) - _x11_elm_object_cnp_selection_clear(sel->widget, type); - e = calloc(1, sizeof(Elm_Cnp_Event_Selection_Changed)); - EINA_SAFETY_ON_NULL_RETURN_VAL(e, ECORE_CALLBACK_RENEW); - e->type = type; - e->seat_id = 1; /* under x11 this is always the default seat */ - e->exists = !!ev->owner; - ecore_event_add(ELM_CNP_EVENT_SELECTION_CHANGED, e, NULL, NULL); - return ECORE_CALLBACK_RENEW; -} - -/* - * Response to a selection notify: - * - So we have asked for the selection list. - * - If it's the targets list, parse it, and fire of what we want, - * else it's the data we want. - */ -static Eina_Bool -_x11_selection_notify(void *udata EINA_UNUSED, int type EINA_UNUSED, void *event) -{ - Ecore_X_Event_Selection_Notify *ev = event; - X11_Cnp_Selection *sel; - int i; - - cnp_debug("selection notify callback: %d\n",ev->selection); - switch (ev->selection) - { - case ECORE_X_SELECTION_PRIMARY: - sel = _x11_selections + ELM_SEL_TYPE_PRIMARY; - break; - case ECORE_X_SELECTION_SECONDARY: - sel = _x11_selections + ELM_SEL_TYPE_SECONDARY; - break; - case ECORE_X_SELECTION_XDND: - sel = _x11_selections + ELM_SEL_TYPE_XDND; - break; - case ECORE_X_SELECTION_CLIPBOARD: - sel = _x11_selections + ELM_SEL_TYPE_CLIPBOARD; - break; - default: - return ECORE_CALLBACK_PASS_ON; - } - cnp_debug("Target is %s\n", ev->target); - - if (ev->selection != ECORE_X_SELECTION_XDND && - (!strcmp(ev->target, "TARGETS") || !strcmp(ev->target, "ATOMS"))) - { - _x11_notify_handler_targets(sel, ev); - return ECORE_CALLBACK_PASS_ON; - } - for (i = 0; i < CNP_N_ATOMS; i++) - { - if (!strcmp(ev->target, _atoms[i].name)) - { - if (_atoms[i].x_data_preparer) - { - Elm_Selection_Data ddata; - Tmp_Info *tmp_info = NULL; - Eina_Bool success; - ddata.data = NULL; - cnp_debug("Found something: %s\n", _atoms[i].name); - success = _atoms[i].x_data_preparer(ev, &ddata, &tmp_info); - if (_atoms[i].formats == ELM_SEL_FORMAT_IMAGE && savedtypes.imgfile) break; - if (ev->selection == ECORE_X_SELECTION_XDND) - { - if (success) - { - Dropable *dropable; - Eina_List *l; - cnp_debug("drag & drop\n"); - EINA_LIST_FOREACH(drops, l, dropable) - { - if (dropable->obj == sel->requestwidget) break; - dropable = NULL; - } - if (dropable) - { - Dropable_Cbs *cbs; - Eina_Inlist *itr; - ddata.x = savedtypes.x; - ddata.y = savedtypes.y; - EINA_INLIST_FOREACH_SAFE(dropable->cbs_list, itr, cbs) - if ((cbs->types & dropable->last.format) && cbs->dropcb) - cbs->dropcb(cbs->dropdata, dropable->obj, &ddata); - } - } - /* We have to finish DnD, no matter what */ - ecore_x_dnd_send_finished(); - } - else if (sel->datacb && success) - { - ddata.x = ddata.y = 0; - sel->datacb(sel->udata, sel->requestwidget, &ddata); - } - free(ddata.data); - if (tmp_info) _tmpinfo_free(tmp_info); - } - else cnp_debug("Ignored: No handler!\n"); - break; - } - } - return ECORE_CALLBACK_PASS_ON; -} - -static Elm_Sel_Format -_get_selection_type(void *data, int size) -{ - if (size == sizeof(Elm_Sel_Type)) - { - unsigned int seltype = *((unsigned int *)data); - if (seltype > ELM_SEL_TYPE_CLIPBOARD) - return ELM_SEL_FORMAT_NONE; - X11_Cnp_Selection *sel = _x11_selections + seltype; - if (sel->active && - (sel->format >= ELM_SEL_FORMAT_TARGETS) && - (sel->format <= ELM_SEL_FORMAT_HTML)) - return sel->format; - } - return ELM_SEL_FORMAT_NONE; -} - -static Eina_Bool -_x11_targets_converter(char *target EINA_UNUSED, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize) -{ - int i, count; - Ecore_X_Atom *aret; - X11_Cnp_Selection *sel; - Elm_Sel_Format seltype; - - if (!data_ret) return EINA_FALSE; - if (_get_selection_type(data, size) == ELM_SEL_FORMAT_NONE) - { - /* TODO : fallback into precise type */ - seltype = ELM_SEL_FORMAT_TEXT; - } - else - { - sel = _x11_selections + *((int *)data); - seltype = sel->format; - } - - for (i = CNP_ATOM_LISTING_ATOMS + 1, count = 0; i < CNP_N_ATOMS ; i++) - { - if (seltype & _atoms[i].formats) count++; - } - aret = malloc(sizeof(Ecore_X_Atom) * count); - if (!aret) return EINA_FALSE; - for (i = CNP_ATOM_LISTING_ATOMS + 1, count = 0; i < CNP_N_ATOMS ; i++) - { - if (seltype & _atoms[i].formats) - aret[count ++] = _atoms[i].x_atom; - } - - *data_ret = aret; - if (typesize) *typesize = 32 /* urk */; - if (ttype) *ttype = ECORE_X_ATOM_ATOM; - if (size_ret) *size_ret = count; - return EINA_TRUE; -} - -static Eina_Bool -_x11_image_converter(char *target EINA_UNUSED, void *data EINA_UNUSED, int size EINA_UNUSED, void **data_ret EINA_UNUSED, int *size_ret EINA_UNUSED, Ecore_X_Atom *ttype EINA_UNUSED, int *typesize EINA_UNUSED) -{ - cnp_debug("Image converter called\n"); - return EINA_TRUE; -} - -static Eina_Bool -_x11_vcard_send(char *target EINA_UNUSED, void *data EINA_UNUSED, int size EINA_UNUSED, void **data_ret, int *size_ret, Ecore_X_Atom *ttype EINA_UNUSED, int *typesize EINA_UNUSED) -{ - X11_Cnp_Selection *sel; - - cnp_debug("Vcard send called\n"); - sel = _x11_selections + *((int *)data); - if (data_ret) *data_ret = strdup(sel->selbuf); - if (size_ret) *size_ret = strlen(sel->selbuf); - return EINA_TRUE; -} - -static Eina_Bool -_x11_is_uri_type_data(X11_Cnp_Selection *sel EINA_UNUSED, Ecore_X_Event_Selection_Notify *notify) -{ - Ecore_X_Selection_Data *data; - char *p; - - data = notify->data; - cnp_debug("data->format is %d %p %p\n", data->format, notify, data); - if (data->content == ECORE_X_SELECTION_CONTENT_FILES) return EINA_TRUE; - p = (char *)data->data; - if (!p) return EINA_TRUE; - cnp_debug("Got %s\n", p); - if (strncmp(p, "file:/", 6)) - { - if (*p != '/') return EINA_FALSE; - } - return EINA_TRUE; -} - -/* - * Callback to handle a targets response on a selection request: - * So pick the format we'd like; and then request it. - */ -static Eina_Bool -_x11_notify_handler_targets(X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify) -{ - Ecore_X_Selection_Data_Targets *targets; - Ecore_X_Atom *atomlist; - int i, j; - - targets = notify->data; - atomlist = (Ecore_X_Atom *)(targets->data.data); - for (j = (CNP_ATOM_LISTING_ATOMS + 1); j < CNP_N_ATOMS; j++) - { - cnp_debug("\t%s %d\n", _atoms[j].name, _atoms[j].x_atom); - if (!(_atoms[j].formats & sel->requestformat)) continue; - for (i = 0; i < targets->data.length; i++) - { - if ((_atoms[j].x_atom == atomlist[i]) && (_atoms[j].x_data_preparer)) - { - if (j == CNP_ATOM_text_urilist) - { - if (!_x11_is_uri_type_data(sel, notify)) continue; - } - cnp_debug("Atom %s matches\n", _atoms[j].name); - goto done; - } - } - } - cnp_debug("Couldn't find anything that matches\n"); - return ECORE_CALLBACK_PASS_ON; -done: - cnp_debug("Sending request for %s, xwin=%#llx\n", - _atoms[j].name, (unsigned long long)sel->xwin); - sel->request(sel->xwin, _atoms[j].name); - return ECORE_CALLBACK_PASS_ON; -} - -static Eina_Bool -_x11_data_preparer_text(Ecore_X_Event_Selection_Notify *notify, - Elm_Selection_Data *ddata, Tmp_Info **tmp_info EINA_UNUSED) -{ - Ecore_X_Selection_Data *data = notify->data; - ddata->format = ELM_SEL_FORMAT_TEXT; - ddata->data = eina_memdup(data->data, data->length, EINA_TRUE); - ddata->len = data->length; - return EINA_TRUE; -} - -static Eina_Bool -_x11_data_preparer_markup(Ecore_X_Event_Selection_Notify *notify, - Elm_Selection_Data *ddata, Tmp_Info **tmp_info EINA_UNUSED) -{ - Ecore_X_Selection_Data *data = notify->data; - ddata->format = ELM_SEL_FORMAT_MARKUP; - ddata->data = eina_memdup(data->data, data->length, EINA_TRUE); - ddata->len = data->length; - return EINA_TRUE; -} - -/** - * So someone is pasting an image into my entry or widget... - */ -static Eina_Bool -_x11_data_preparer_uri(Ecore_X_Event_Selection_Notify *notify, - Elm_Selection_Data *ddata, Tmp_Info **tmp_info EINA_UNUSED) -{ - Ecore_X_Selection_Data *data; - Ecore_X_Selection_Data_Files *files; - char *p, *stripstr = NULL; - - data = notify->data; - cnp_debug("data->format is %d %p %p\n", data->format, notify, data); - if (data->content == ECORE_X_SELECTION_CONTENT_FILES) - { - Efreet_Uri *uri; - Eina_Strbuf *strbuf; - int i; - - cnp_debug("got a files list\n"); - files = notify->data; - /* - if (files->num_files > 1) - { - // Don't handle many items <- this makes mr bigglesworth sad :( - cnp_debug("more then one file: Bailing\n"); - return EINA_FALSE; - } - stripstr = p = strdup(files->files[0]); - */ - - strbuf = eina_strbuf_new(); - if (!strbuf) - return EINA_FALSE; - - for (i = 0; i < files->num_files ; i++) - { - uri = efreet_uri_decode(files->files[i]); - if (uri) - { - eina_strbuf_append(strbuf, uri->path); - efreet_uri_free(uri); - } - else - { - eina_strbuf_append(strbuf, files->files[i]); - } - if (i < (files->num_files - 1)) - eina_strbuf_append(strbuf, "\n"); - } - stripstr = eina_strbuf_string_steal(strbuf); - eina_strbuf_free(strbuf); - } - else - { - Efreet_Uri *uri; - - p = (char *)eina_memdup((unsigned char *)data->data, data->length, EINA_TRUE); - if (!p) return EINA_FALSE; - uri = efreet_uri_decode(p); - if (!uri) - { - /* Is there any reason why we care of URI without scheme? */ - if (p[0] == '/') stripstr = p; - else free(p); - } - else - { - free(p); - stripstr = strdup(uri->path); - efreet_uri_free(uri); - } - } - - if (!stripstr) - { - cnp_debug("Couldn't find a file\n"); - return EINA_FALSE; - } - free(savedtypes.imgfile); - if (savedtypes.textreq) - { - savedtypes.textreq = 0; - savedtypes.imgfile = stripstr; - } - else - { - ddata->format = ELM_SEL_FORMAT_IMAGE; - ddata->data = stripstr; - ddata->len = strlen(stripstr); - savedtypes.imgfile = NULL; - } - return EINA_TRUE; -} - -/** - * Just received an vcard, either through cut and paste, or dnd. - */ -static Eina_Bool -_x11_data_preparer_vcard(Ecore_X_Event_Selection_Notify *notify, - Elm_Selection_Data *ddata, Tmp_Info **tmp_info EINA_UNUSED) -{ - cnp_debug("vcard receive\n"); - Ecore_X_Selection_Data *data = notify->data; - ddata->format = ELM_SEL_FORMAT_VCARD; - ddata->data = eina_memdup(data->data, data->length, EINA_TRUE); - ddata->len = data->length; - return EINA_TRUE; -} - -static Eina_Bool -_x11_data_preparer_image(Ecore_X_Event_Selection_Notify *notify, - Elm_Selection_Data *ddata, Tmp_Info **tmp_info) -{ - Ecore_X_Selection_Data *data = notify->data; - cnp_debug("got a image file!\n"); - cnp_debug("Size if %d\n", data->length); - - ddata->format = ELM_SEL_FORMAT_IMAGE; - data = notify->data; - - Tmp_Info *tmp = _tempfile_new(data->length); - if (!tmp) return EINA_FALSE; - memcpy(tmp->map, data->data, data->length); - munmap(tmp->map, data->length); - ddata->data = strdup(tmp->filename); - ddata->len = strlen(tmp->filename); - *tmp_info = tmp; - return EINA_TRUE; -} - -/** - * Warning: Generic text/html can';t handle it sanely. - * Firefox sends ucs2 (i think). - * chrome sends utf8... blerg - */ -/* -static int -_x11_notify_handler_html(X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify) -{ - Ecore_X_Selection_Data *data; - - cnp_debug("Got some HTML: Checking encoding is useful\n"); - data = notify->data; - char *stripstr = malloc(data->length + 1); - if (!stripstr) return 0; - strncpy(stripstr, (char *)data->data, data->length); - stripstr[data->length] = '\0'; - - if (sel->datacb) - { - Elm_Selection_Data ddata; - ddata.x = ddata.y = 0; - ddata.format = ELM_SEL_FORMAT_HTML; - ddata.data = stripstr; - ddata.len = data->length; - ddata.action = ELM_XDND_ACTION_UNKNOWN; - sel->datacb(sel->udata, sel->widget, &ddata); - free(stripstr); - return 0; - } - - cnp_debug("String is %s (%d bytes)\n", stripstr, data->length); - // TODO BUG: should never NEVER assume it's an elm_entry! - _elm_entry_entry_paste(sel->requestwidget, stripstr); - free(stripstr); - return 0; -} -*/ - -static Eina_Bool -_x11_text_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize) -{ - X11_Cnp_Selection *sel; - - cnp_debug("text converter\n"); - if (_get_selection_type(data, size) == ELM_SEL_FORMAT_NONE) - { - if (data_ret) - { - *data_ret = malloc(size * sizeof(char) + 1); - if (!*data_ret) return EINA_FALSE; - memcpy(*data_ret, data, size); - ((char**)(data_ret))[0][size] = 0; - } - if (size_ret) *size_ret = size; - return EINA_TRUE; - } - sel = _x11_selections + *((int *)data); - if (!sel->active) return EINA_TRUE; - - if ((sel->format & ELM_SEL_FORMAT_MARKUP) || - (sel->format & ELM_SEL_FORMAT_HTML)) - { - *data_ret = _elm_util_mkup_to_text(sel->selbuf); - if (size_ret && *data_ret) *size_ret = strlen(*data_ret); - } - else if (sel->format & ELM_SEL_FORMAT_TEXT) - { - ecore_x_selection_converter_text(target, sel->selbuf, - strlen(sel->selbuf), - data_ret, size_ret, - ttype, typesize); - } - else if (sel->format & ELM_SEL_FORMAT_IMAGE) - { - cnp_debug("Image %s\n", evas_object_type_get(sel->widget)); - cnp_debug("Elm type: %s\n", elm_object_widget_type_get(sel->widget)); - evas_object_image_file_get(elm_photocam_internal_image_get(sel->widget), - (const char **)data_ret, NULL); - if (!*data_ret) *data_ret = strdup("No file"); - else *data_ret = strdup(*data_ret); - - if (!*data_ret) - { - ERR("Failed to allocate memory!"); - *size_ret = 0; - return EINA_FALSE; - } - - *size_ret = strlen(*data_ret); - } - return EINA_TRUE; -} - -static Eina_Bool -_x11_general_converter(char *target EINA_UNUSED, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype EINA_UNUSED, int *typesize EINA_UNUSED) -{ - if (_get_selection_type(data, size) == ELM_SEL_FORMAT_NONE) - { - if (data_ret) - { - *data_ret = malloc(size * sizeof(char) + 1); - if (!*data_ret) return EINA_FALSE; - memcpy(*data_ret, data, size); - ((char**)(data_ret))[0][size] = 0; - } - if (size_ret) *size_ret = size; - } - else - { - X11_Cnp_Selection *sel = _x11_selections + *((int *)data); - if (sel->selbuf) - { - if (data_ret) *data_ret = strdup(sel->selbuf); - if (size_ret) *size_ret = strlen(sel->selbuf); - } - else - { - if (data_ret) *data_ret = NULL; - if (size_ret) *size_ret = 0; - } - } - return EINA_TRUE; -} - -static Dropable * -_x11_dropable_find(Ecore_X_Window win) -{ - Eina_List *l; - Dropable *dropable; - - if (!drops) return NULL; - EINA_LIST_FOREACH(drops, l, dropable) - { - if (_x11_elm_widget_xwin_get(dropable->obj) == win) return dropable; - } - return NULL; -} - -static Evas * -_x11_evas_get_from_xwin(Ecore_X_Window win) -{ - /* Find the Evas connected to the window */ - Dropable *dropable = _x11_dropable_find(win); - return dropable ? evas_object_evas_get(dropable->obj) : NULL; -} - -static Eina_Bool -_x11_dnd_enter(void *data EINA_UNUSED, int etype EINA_UNUSED, void *ev) -{ - Ecore_X_Event_Xdnd_Enter *enter = ev; - int i; - Dropable *dropable; - - if (!enter) return EINA_TRUE; - dropable = _x11_dropable_find(enter->win); - if (dropable) - { - cnp_debug("Enter %x\n", enter->win); - } - /* Skip it */ - cnp_debug("enter types=%p (%d)\n", enter->types, enter->num_types); - if ((!enter->num_types) || (!enter->types)) return EINA_TRUE; - - cnp_debug("Types\n"); - savedtypes.ntypes = enter->num_types; - free(savedtypes.types); - savedtypes.types = malloc(sizeof(char *) * enter->num_types); - if (!savedtypes.types) return EINA_FALSE; - - for (i = 0; i < enter->num_types; i++) - { - savedtypes.types[i] = eina_stringshare_add(enter->types[i]); - cnp_debug("Type is %s %p %p\n", enter->types[i], - savedtypes.types[i], text_uri); - if (savedtypes.types[i] == text_uri) - { - /* Request it, so we know what it is */ - cnp_debug("Sending uri request\n"); - savedtypes.textreq = 1; - ELM_SAFE_FREE(savedtypes.imgfile, free); - ecore_x_selection_xdnd_request(enter->win, text_uri); - } - } - - /* FIXME: Find an object and make it current */ - return EINA_TRUE; -} - -static void -_x11_dnd_dropable_handle(Dropable *dropable, Evas_Coord x, Evas_Coord y, Elm_Xdnd_Action action) -{ - Dropable *d, *last_dropable = NULL; - Eina_List *l; - Dropable_Cbs *cbs; - Eina_Inlist *itr; - - EINA_LIST_FOREACH(drops, l, d) - { - if (d->last.in) - { - last_dropable = d; - break; - } - } - if (last_dropable) - { - if (last_dropable == dropable) // same - { - Evas_Coord ox, oy; - - cnp_debug("same obj dropable %p\n", dropable->obj); - evas_object_geometry_get(dropable->obj, &ox, &oy, NULL, NULL); - EINA_INLIST_FOREACH_SAFE(dropable->cbs_list, itr, cbs) - if ((cbs->types & dropable->last.format) && cbs->poscb) - cbs->poscb(cbs->posdata, dropable->obj, x - ox, y - oy, action); - } - else - { - if (dropable) // leave last obj and enter new one - { - cnp_debug("leave %p\n", last_dropable->obj); - cnp_debug("enter %p\n", dropable->obj); - last_dropable->last.in = EINA_FALSE; - last_dropable->last.type = NULL; - dropable->last.in = EINA_TRUE; - EINA_INLIST_FOREACH_SAFE(dropable->cbs_list, itr, cbs) - if ((cbs->types & dropable->last.format) && cbs->entercb) - cbs->entercb(cbs->enterdata, dropable->obj); - EINA_INLIST_FOREACH_SAFE(last_dropable->cbs_list, itr, cbs) - if ((cbs->types & last_dropable->last.format) && cbs->leavecb) - cbs->leavecb(cbs->leavedata, last_dropable->obj); - } - else // leave last obj - { - cnp_debug("leave %p\n", last_dropable->obj); - last_dropable->last.in = EINA_FALSE; - last_dropable->last.type = NULL; - EINA_INLIST_FOREACH_SAFE(last_dropable->cbs_list, itr, cbs) - if ((cbs->types & last_dropable->last.format) && cbs->leavecb) - cbs->leavecb(cbs->leavedata, last_dropable->obj); - } - } - } - else - { - if (dropable) // enter new obj - { - Evas_Coord ox, oy; - - cnp_debug("enter %p\n", dropable->obj); - evas_object_geometry_get(dropable->obj, &ox, &oy, NULL, NULL); - dropable->last.in = EINA_TRUE; - EINA_INLIST_FOREACH_SAFE(dropable->cbs_list, itr, cbs) - { - if (cbs->types & dropable->last.format) - { - if (cbs->entercb) - cbs->entercb(cbs->enterdata, dropable->obj); - if (cbs->poscb) - cbs->poscb(cbs->posdata, dropable->obj, - x - ox, y - oy, action); - } - } - } - else - { - cnp_debug("both dropable & last_dropable are null\n"); - } - } -} - -static Elm_Xdnd_Action -_x11_dnd_action_map(Ecore_X_Atom action) -{ - Elm_Xdnd_Action act = ELM_XDND_ACTION_UNKNOWN; - - if (action == ECORE_X_ATOM_XDND_ACTION_COPY) - act = ELM_XDND_ACTION_COPY; - else if (action == ECORE_X_ATOM_XDND_ACTION_MOVE) - act = ELM_XDND_ACTION_MOVE; - else if (action == ECORE_X_ATOM_XDND_ACTION_PRIVATE) - act = ELM_XDND_ACTION_PRIVATE; - else if (action == ECORE_X_ATOM_XDND_ACTION_ASK) - act = ELM_XDND_ACTION_ASK; - else if (action == ECORE_X_ATOM_XDND_ACTION_LIST) - act = ELM_XDND_ACTION_LIST; - else if (action == ECORE_X_ATOM_XDND_ACTION_LINK) - act = ELM_XDND_ACTION_LINK; - else if (action == ECORE_X_ATOM_XDND_ACTION_DESCRIPTION) - act = ELM_XDND_ACTION_DESCRIPTION; - return act; -} - -static Ecore_X_Atom -_x11_dnd_action_rev_map(Elm_Xdnd_Action action) -{ - Ecore_X_Atom act = ECORE_X_ATOM_XDND_ACTION_MOVE; - - if (action == ELM_XDND_ACTION_COPY) - act = ECORE_X_ATOM_XDND_ACTION_COPY; - else if (action == ELM_XDND_ACTION_MOVE) - act = ECORE_X_ATOM_XDND_ACTION_MOVE; - else if (action == ELM_XDND_ACTION_PRIVATE) - act = ECORE_X_ATOM_XDND_ACTION_PRIVATE; - else if (action == ELM_XDND_ACTION_ASK) - act = ECORE_X_ATOM_XDND_ACTION_ASK; - else if (action == ELM_XDND_ACTION_LIST) - act = ECORE_X_ATOM_XDND_ACTION_LIST; - else if (action == ELM_XDND_ACTION_LINK) - act = ECORE_X_ATOM_XDND_ACTION_LINK; - else if (action == ELM_XDND_ACTION_DESCRIPTION) - act = ECORE_X_ATOM_XDND_ACTION_DESCRIPTION; - return act; -} - -static Eina_Bool -_x11_dnd_position(void *data EINA_UNUSED, int etype EINA_UNUSED, void *ev) -{ - Ecore_X_Event_Xdnd_Position *pos = ev; - Ecore_X_Rectangle rect = { 0, 0, 0, 0 }; - Dropable *dropable; - Elm_Xdnd_Action act; - - /* Need to send a status back */ - /* FIXME: Should check I can drop here */ - /* FIXME: Should highlight widget */ - dropable = _x11_dropable_find(pos->win); - if (dropable) - { - Evas_Coord x, y, ox = 0, oy = 0; - - act = _x11_dnd_action_map(pos->action); - x = pos->position.x; - y = pos->position.y; - _dropable_coords_adjust(dropable, &x, &y); - Evas *evas = _x11_evas_get_from_xwin(pos->win); - Eina_List *dropable_list = evas ? _dropable_list_geom_find(evas, x, y) : NULL; - /* check if there is dropable (obj) can accept this drop */ - if (dropable_list) - { - Elm_Sel_Format saved_format = _dnd_types_to_format(savedtypes.types, savedtypes.ntypes); - Eina_List *l; - Eina_Bool found = EINA_FALSE; - - EINA_LIST_FOREACH(dropable_list, l, dropable) - { - Dropable_Cbs *cbs; - Eina_Inlist *itr; - EINA_INLIST_FOREACH_SAFE(dropable->cbs_list, itr, cbs) - { - Elm_Sel_Format common_fmt = saved_format & cbs->types; - if (common_fmt) - { - /* We found a target that can accept this type of data */ - int i, min_index = CNP_N_ATOMS; - /* We have to find the first atom that corresponds to one - * of the supported data types. */ - for (i = 0; i < savedtypes.ntypes; i++) - { - Cnp_Atom *atom = eina_hash_find(_types_hash, savedtypes.types[i]); - if (atom && (atom->formats & common_fmt)) - { - int atom_idx = (atom - _atoms); - if (min_index > atom_idx) min_index = atom_idx; - } - } - if (min_index != CNP_N_ATOMS) - { - cnp_debug("Found atom %s\n", _atoms[min_index].name); - found = EINA_TRUE; - dropable->last.type = _atoms[min_index].name; - dropable->last.format = common_fmt; - break; - } - } - } - if (found) break; - } - if (found) - { - Dropable *d = NULL; - Eina_Rectangle inter_rect = {0, 0, 0, 0}; - int idx = 0; - EINA_LIST_FOREACH(dropable_list, l, d) - { - if (idx == 0) - { - evas_object_geometry_get(d->obj, &inter_rect.x, &inter_rect.y, - &inter_rect.w, &inter_rect.h); - } - else - { - Eina_Rectangle cur_rect; - evas_object_geometry_get(d->obj, &cur_rect.x, &cur_rect.y, - &cur_rect.w, &cur_rect.h); - if (!eina_rectangle_intersection(&inter_rect, &cur_rect)) continue; - } - idx++; - } - rect.x = inter_rect.x; - rect.y = inter_rect.y; - rect.width = inter_rect.w; - rect.height = inter_rect.h; - ecore_x_dnd_send_status(EINA_TRUE, EINA_FALSE, rect, pos->action); - cnp_debug("dnd position %i %i %p\n", x - ox, y - oy, dropable); - _x11_dnd_dropable_handle(dropable, x - ox, y - oy, act); - // CCCCCCC: call dnd exit on last obj if obj != last - // CCCCCCC: call drop position on obj - } - else - { - //if not: send false status - ecore_x_dnd_send_status(EINA_FALSE, EINA_FALSE, rect, pos->action); - cnp_debug("dnd position (%d, %d) not in obj\n", x, y); - _x11_dnd_dropable_handle(NULL, 0, 0, act); - // CCCCCCC: call dnd exit on last obj - } - eina_list_free(dropable_list); - } - else - { - ecore_x_dnd_send_status(EINA_FALSE, EINA_FALSE, rect, pos->action); - cnp_debug("dnd position (%d, %d) has no drop\n", x, y); - _x11_dnd_dropable_handle(NULL, 0, 0, act); - } - } - else - { - ecore_x_dnd_send_status(EINA_FALSE, EINA_FALSE, rect, pos->action); - } - return EINA_TRUE; -} - -static Eina_Bool -_x11_dnd_leave(void *data EINA_UNUSED, int etype EINA_UNUSED, void *ev) -{ -#ifdef DEBUGON - cnp_debug("Leave %x\n", ((Ecore_X_Event_Xdnd_Leave *)ev)->win); -#else - (void)ev; -#endif - _x11_dnd_dropable_handle(NULL, 0, 0, ELM_XDND_ACTION_UNKNOWN); - // CCCCCCC: call dnd exit on last obj if there was one - // leave->win leave->source - return EINA_TRUE; -} - -static Eina_Bool -_x11_dnd_drop(void *data EINA_UNUSED, int etype EINA_UNUSED, void *ev) -{ - Ecore_X_Event_Xdnd_Drop *drop; - Dropable *dropable = NULL; - Elm_Selection_Data ddata; - Evas_Coord x = 0, y = 0; - Elm_Xdnd_Action act = ELM_XDND_ACTION_UNKNOWN; - Eina_List *l; - Dropable_Cbs *cbs; - Eina_Inlist *itr; - - drop = ev; - - cnp_debug("drops %p (%d)\n", drops, eina_list_count(drops)); - if (!(dropable = _x11_dropable_find(drop->win))) return EINA_TRUE; - - /* Calculate real (widget relative) position */ - // - window position - // - widget position - savedtypes.x = drop->position.x; - savedtypes.y = drop->position.y; - _dropable_coords_adjust(dropable, &savedtypes.x, &savedtypes.y); - - cnp_debug("Drop position is %d,%d\n", savedtypes.x, savedtypes.y); - - EINA_LIST_FOREACH(drops, l, dropable) - { - if (dropable->last.in) - { - evas_object_geometry_get(dropable->obj, &x, &y, NULL, NULL); - savedtypes.x -= x; - savedtypes.y -= y; - goto found; - } - } - - cnp_debug("Didn't find a target\n"); - return EINA_TRUE; - -found: - cnp_debug("0x%x\n", drop->win); - - act = _x11_dnd_action_map(drop->action); - - dropable->last.in = EINA_FALSE; - cnp_debug("Last type: %s - Last format: %X\n", dropable->last.type, dropable->last.format); - if ((!strcmp(dropable->last.type, text_uri))) - { - cnp_debug("We found a URI... (%scached) %s\n", - savedtypes.imgfile ? "" : "not ", - savedtypes.imgfile); - if (savedtypes.imgfile) - { - ddata.x = savedtypes.x; - ddata.y = savedtypes.y; - ddata.action = act; - - EINA_INLIST_FOREACH_SAFE(dropable->cbs_list, itr, cbs) - { - /* If it's markup that also supports images */ - if (cbs->types & ELM_SEL_FORMAT_IMAGE) - { - cnp_debug("Doing image insert (%s)\n", savedtypes.imgfile); - ddata.format = ELM_SEL_FORMAT_IMAGE; - ddata.data = (char *)savedtypes.imgfile; - ddata.len = strlen(ddata.data); - if ((cbs->types & dropable->last.format) && cbs->dropcb) - cbs->dropcb(cbs->dropdata, dropable->obj, &ddata); - } - else - { - cnp_debug("Item doesn't support images... passing\n"); - } - } - ecore_x_dnd_send_finished(); - ELM_SAFE_FREE(savedtypes.imgfile, free); - return EINA_TRUE; - } - else if (savedtypes.textreq) - { - /* Already asked: Pretend we asked now, and paste immediately when - * it comes in */ - savedtypes.textreq = 0; - ecore_x_dnd_send_finished(); - return EINA_TRUE; - } - } - - cnp_debug("doing a request then: %s\n", dropable->last.type); - _x11_selections[ELM_SEL_TYPE_XDND].xwin = drop->win; - _x11_selections[ELM_SEL_TYPE_XDND].requestwidget = dropable->obj; - _x11_selections[ELM_SEL_TYPE_XDND].requestformat = dropable->last.format; - _x11_selections[ELM_SEL_TYPE_XDND].active = EINA_TRUE; - _x11_selections[ELM_SEL_TYPE_XDND].action = act; - ecore_x_selection_xdnd_request(drop->win, dropable->last.type); - return EINA_TRUE; -} - -static Eina_Bool -_x11_dnd_status(void *data EINA_UNUSED, int etype EINA_UNUSED, void *ev) -{ - Ecore_X_Event_Xdnd_Status *status = ev; - - doaccept = EINA_FALSE; - - /* Only thing we care about: will accept */ - if ((status) && (status->will_accept)) - { - cnp_debug("Will accept\n"); - doaccept = EINA_TRUE; - } - /* Won't accept */ - else - { - cnp_debug("Won't accept accept\n"); - } - if (dragacceptcb) - dragacceptcb(dragacceptdata, _x11_selections[ELM_SEL_TYPE_XDND].widget, - doaccept); - return EINA_TRUE; -} - -static void -_x11_win_rotation_changed_cb(void *data, const Efl_Event *event) -{ - Evas_Object *win = data; - int rot = elm_win_rotation_get(event->object); - elm_win_rotation_set(win, rot); -} - -static Eina_Bool -_x11_drag_mouse_up(void *data, int etype EINA_UNUSED, void *event) -{ - Ecore_X_Window xwin = (Ecore_X_Window)(long)data; - Ecore_Event_Mouse_Button *ev = event; - - if ((ev->buttons == 1) && - (ev->event_window == xwin)) - { - Eina_Bool have_drops = EINA_FALSE; - Eina_List *l; - Dropable *dropable; - - ecore_x_pointer_ungrab(); - ELM_SAFE_FREE(handler_up, ecore_event_handler_del); - ELM_SAFE_FREE(handler_status, ecore_event_handler_del); - ecore_x_dnd_self_drop(); - - cnp_debug("mouse up, xwin=%#llx\n", (unsigned long long)xwin); - - EINA_LIST_FOREACH(drops, l, dropable) - { - if (xwin == _x11_elm_widget_xwin_get(dropable->obj)) - { - have_drops = EINA_TRUE; - break; - } - } - if (!have_drops) ecore_x_dnd_aware_set(xwin, EINA_FALSE); - if (dragdonecb) dragdonecb(dragdonedata, dragwidget); - if (dragwin) - { - if (dragwidget) - { - if (elm_widget_is(dragwidget)) - { - Evas_Object *win = elm_widget_top_get(dragwidget); - if (win && efl_isa(win, EFL_UI_WIN_CLASS)) - efl_event_callback_del(win, EFL_UI_WIN_EVENT_ROTATION_CHANGED, _x11_win_rotation_changed_cb, dragwin); - } - } - - if (!doaccept) - { /* Commit animation when drag cancelled */ - /* Record final position of dragwin, then do animation */ - ecore_animator_timeline_add(0.3, - _drag_cancel_animate, dragwin); - } - else - { /* No animation drop was committed */ - Ecore_X_Window xdragwin = _x11_elm_widget_xwin_get(dragwin); - ecore_x_window_ignore_set(xdragwin, 0); - evas_object_del(dragwin); - } - - dragwin = NULL; /* if not freed here, free in end of anim */ - } - - dragdonecb = NULL; - dragacceptcb = NULL; - dragposcb = NULL; - dragwidget = NULL; - doaccept = EINA_FALSE; - /* moved to _drag_cancel_animate - if (dragwin) - { - evas_object_del(dragwin); - dragwin = NULL; - } - */ - } - return EINA_TRUE; -} - -static void -_x11_drag_move(void *data EINA_UNUSED, Ecore_X_Xdnd_Position *pos) -{ - evas_object_move(dragwin, - pos->position.x - _dragx, pos->position.y - _dragy); - dragwin_x_end = pos->position.x - _dragx; - dragwin_y_end = pos->position.y - _dragy; - cnp_debug("dragevas: %p -> %p\n", - dragwidget, - evas_object_evas_get(dragwidget)); - if (dragposcb) - dragposcb(dragposdata, dragwidget, pos->position.x, pos->position.y, - dragaction); -} - -static Ecore_X_Window -_x11_elm_widget_xwin_get(const Evas_Object *obj) -{ - Evas_Object *top, *par; - Ecore_X_Window xwin = 0; - - if (elm_widget_is(obj)) - { - top = elm_widget_top_get(obj); - if (!top) - { - par = elm_widget_parent_widget_get(obj); - if (par) top = elm_widget_top_get(par); - } - if (top && (efl_isa(top, EFL_UI_WIN_CLASS))) - xwin = elm_win_xwindow_get(top); - } - if (!xwin) - { - Ecore_Evas *ee; - Evas *evas = evas_object_evas_get(obj); - if (!evas) return 0; - ee = ecore_evas_ecore_evas_get(evas); - if (!ee) return 0; - - while(!xwin) - { - const char *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 0; - xwin = _elm_ee_xwin_get(ee); - } - else - { - /* In case the engine is not a buffer, we want to check once. */ - xwin = _elm_ee_xwin_get(ee); - if (!xwin) return 0; - } - } - } - return xwin; -} - -static Eina_Bool -_x11_elm_cnp_init(void) -{ - int i; - static int _init_count = 0; - - if (_init_count > 0) return EINA_TRUE; - _init_count++; - for (i = 0; i < CNP_N_ATOMS; i++) - { - _atoms[i].x_atom = ecore_x_atom_get(_atoms[i].name); - ecore_x_selection_converter_atom_add - (_atoms[i].x_atom, _atoms[i].x_converter); - } - //XXX delete handlers? - ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, _x11_selection_clear, NULL); - ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, _x11_selection_notify, NULL); - ecore_event_handler_add(ECORE_X_EVENT_FIXES_SELECTION_NOTIFY, _x11_fixes_selection_notify, NULL); - return EINA_TRUE; -} - -static Eina_Bool -_x11_elm_cnp_selection_set(Ecore_X_Window xwin, Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, const void *selbuf, size_t buflen) -{ - X11_Cnp_Selection *sel; - - _x11_elm_cnp_init(); - if ((!selbuf) && (format != ELM_SEL_FORMAT_IMAGE)) - return elm_object_cnp_selection_clear(obj, selection); - - sel = _x11_selections + selection; - if (sel->widget != obj && sel->loss_cb) sel->loss_cb(sel->loss_data, selection); - if (sel->widget) - evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL, - _x11_sel_obj_del, sel); - sel->active = EINA_TRUE; - sel->widget = obj; - sel->xwin = xwin; - if (sel->set) sel->set(xwin, &selection, sizeof(Elm_Sel_Type)); - sel->format = format; - sel->loss_cb = NULL; - sel->loss_data = NULL; - - evas_object_event_callback_add - (sel->widget, EVAS_CALLBACK_DEL, _x11_sel_obj_del, sel); - - ELM_SAFE_FREE(sel->selbuf, free); - if (selbuf) - { - if (format == ELM_SEL_FORMAT_IMAGE) - { - // selbuf is actual image data, not text/string - sel->selbuf = malloc(buflen + 1); - if (!sel->selbuf) - { - elm_object_cnp_selection_clear(obj, selection); - return EINA_FALSE; - } - memcpy(sel->selbuf, selbuf, buflen); - sel->selbuf[buflen] = 0; - } - else - sel->selbuf = strdup((char*)selbuf); - } - - return _local_elm_cnp_selection_set(obj, selection, format, selbuf, buflen); -} - -static void -_x11_elm_cnp_selection_loss_callback_set(Evas_Object *obj EINA_UNUSED, Elm_Sel_Type selection, Elm_Selection_Loss_Cb func, const void *data) -{ - X11_Cnp_Selection *sel; - - _x11_elm_cnp_init(); - sel = _x11_selections + selection; - sel->loss_cb = func; - sel->loss_data = (void *)data; -} - -static Eina_Bool -_x11_elm_object_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type selection) -{ - X11_Cnp_Selection *sel; - - _x11_elm_cnp_init(); - - sel = _x11_selections + selection; - - /* No longer this selection: Consider it gone! */ - if ((!sel->active) || (sel->widget != obj)) return EINA_TRUE; - - if (sel->widget) - evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL, - _x11_sel_obj_del, sel); - if (sel->requestwidget) - evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL, - _x11_sel_obj_del2, sel); - sel->widget = NULL; - sel->requestwidget = NULL; - sel->loss_cb = NULL; - sel->loss_data = NULL; - - sel->active = EINA_FALSE; - ELM_SAFE_FREE(sel->selbuf, free); - sel->clear(); - - return _local_elm_object_cnp_selection_clear(obj, selection); -} - -static Eina_Bool -_x11_elm_cnp_selection_get(Ecore_X_Window xwin, const Evas_Object *obj, Elm_Sel_Type selection, - Elm_Sel_Format format, Elm_Drop_Cb datacb, - void *udata) -{ - X11_Cnp_Selection *sel; - - _x11_elm_cnp_init(); - - sel = _x11_selections + selection; - if (sel->active) - return _local_elm_cnp_selection_get(obj, selection, format, datacb, udata); - - if (sel->requestwidget) - evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL, - _x11_sel_obj_del2, sel); - sel->requestformat = format; - sel->requestwidget = (Evas_Object *)obj; - sel->xwin = xwin; - sel->request(xwin, ECORE_X_SELECTION_TARGET_TARGETS); - sel->datacb = datacb; - sel->udata = udata; - - evas_object_event_callback_add - (sel->requestwidget, EVAS_CALLBACK_DEL, _x11_sel_obj_del2, sel); - - return EINA_TRUE; -} - -static Eina_Bool -_x11_elm_drop_target_add(Evas_Object *obj, Elm_Sel_Format format, - Elm_Drag_State entercb, void *enterdata, - Elm_Drag_State leavecb, void *leavedata, - Elm_Drag_Pos poscb, void *posdata, - Elm_Drop_Cb dropcb, void *dropdata) -{ - Dropable *dropable = NULL; - Dropable_Cbs *cbs = NULL; - Ecore_X_Window xwin = _x11_elm_widget_xwin_get(obj); - Eina_List *l; - Eina_Bool first = !drops; - Eina_Bool have_drops = EINA_FALSE; - - _x11_elm_cnp_init(); - - /* Is this the first? */ - EINA_LIST_FOREACH(drops, l, dropable) - { - if (xwin == _x11_elm_widget_xwin_get(dropable->obj)) - { - have_drops = EINA_TRUE; - break; - } - } - dropable = NULL; // In case of error, we don't want to free it - - cbs = calloc(1, sizeof(*cbs)); - if (!cbs) return EINA_FALSE; - - cbs->entercb = entercb; - cbs->enterdata = enterdata; - cbs->leavecb = leavecb; - cbs->leavedata = leavedata; - cbs->poscb = poscb; - cbs->posdata = posdata; - cbs->dropcb = dropcb; - cbs->dropdata = dropdata; - cbs->types = format; - - dropable = efl_key_data_get(obj, "__elm_dropable"); - if (!dropable) - { - /* Create new drop */ - dropable = calloc(1, sizeof(Dropable)); - if (!dropable) goto error; - dropable->last.in = EINA_FALSE; - drops = eina_list_append(drops, dropable); - if (!drops) goto error; - dropable->obj = obj; - efl_key_data_set(obj, "__elm_dropable", dropable); - } - dropable->cbs_list = eina_inlist_append(dropable->cbs_list, EINA_INLIST_GET(cbs)); - - evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, - _all_drop_targets_cbs_del, obj); - if (!have_drops) ecore_x_dnd_aware_set(xwin, EINA_TRUE); - - /* TODO BUG: should handle dnd-aware per window, not just the first - * window that requested it! */ - /* If not the first: We're done */ - if (!first) return EINA_TRUE; - - cnp_debug("Adding drop target calls xwin=%#llx\n", (unsigned long long)xwin); - handler_enter = ecore_event_handler_add(ECORE_X_EVENT_XDND_ENTER, - _x11_dnd_enter, NULL); - handler_leave = ecore_event_handler_add(ECORE_X_EVENT_XDND_LEAVE, - _x11_dnd_leave, NULL); - handler_pos = ecore_event_handler_add(ECORE_X_EVENT_XDND_POSITION, - _x11_dnd_position, NULL); - handler_drop = ecore_event_handler_add(ECORE_X_EVENT_XDND_DROP, - _x11_dnd_drop, NULL); - return EINA_TRUE; -error: - free(cbs); - free(dropable); - return EINA_FALSE; -} - -static Eina_Bool -_x11_elm_drop_target_del(Evas_Object *obj, Elm_Sel_Format format, - Elm_Drag_State entercb, void *enterdata, - Elm_Drag_State leavecb, void *leavedata, - Elm_Drag_Pos poscb, void *posdata, - Elm_Drop_Cb dropcb, void *dropdata) -{ - Dropable *dropable = NULL; - Eina_List *l; - Ecore_X_Window xwin; - Eina_Bool have_drops = EINA_FALSE; - - _x11_elm_cnp_init(); - - if (!_local_elm_drop_target_del(obj, format, entercb, enterdata, - leavecb, leavedata, poscb, posdata, dropcb, dropdata)) - { - return EINA_FALSE; - } - - /* TODO BUG: we should handle dnd-aware per window, not just the last that released it */ - - /* If still drops there: All fine.. continue */ - if (drops) return EINA_TRUE; - - cnp_debug("Disabling DND\n"); - xwin = _x11_elm_widget_xwin_get(obj); - EINA_LIST_FOREACH(drops, l, dropable) - { - if (xwin == _x11_elm_widget_xwin_get(dropable->obj)) - { - have_drops = EINA_TRUE; - break; - } - } - if (!have_drops) ecore_x_dnd_aware_set(xwin, EINA_FALSE); - - if (!drops) - { - ELM_SAFE_FREE(handler_pos, ecore_event_handler_del); - ELM_SAFE_FREE(handler_drop, ecore_event_handler_del); - ELM_SAFE_FREE(handler_enter, ecore_event_handler_del); - ELM_SAFE_FREE(handler_leave, ecore_event_handler_del); - } - - ELM_SAFE_FREE(savedtypes.imgfile, free); - - return EINA_TRUE; -} - -static void -_x11_drag_target_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *info EINA_UNUSED) -{ - X11_Cnp_Selection *sel = _x11_selections + ELM_SEL_TYPE_XDND; - - if (dragwidget == obj) - { - sel->widget = NULL; - dragwidget = NULL; - } -} - -static Eina_Bool -_x11_elm_drag_start(Evas_Object *obj, Elm_Sel_Format format, const char *data, - Elm_Xdnd_Action action, - Elm_Drag_Icon_Create_Cb createicon, void *createdata, - Elm_Drag_Pos dragpos, void *dragdata, - Elm_Drag_Accept acceptcb, void *acceptdata, - Elm_Drag_State dragdone, void *donecbdata) -{ - Ecore_X_Window xwin = _x11_elm_widget_xwin_get(obj); - Ecore_X_Window xdragwin; - X11_Cnp_Selection *sel; - Elm_Sel_Type xdnd = ELM_SEL_TYPE_XDND; - Ecore_Evas *ee; - int x, y, x2 = 0, y2 = 0, x3, y3; - Evas_Object *icon = NULL; - int w = 0, h = 0; - int ex, ey, ew, eh; - Ecore_X_Atom actx; - int i; - int xr, yr, rot; - - _x11_elm_cnp_init(); - - cnp_debug("starting drag... %p\n", obj); - - if (dragwin) - { - cnp_debug("another obj is dragging...\n"); - return EINA_FALSE; - } - - ecore_x_dnd_types_set(xwin, NULL, 0); - for (i = CNP_ATOM_LISTING_ATOMS + 1; i < CNP_N_ATOMS; i++) - { - if (format == ELM_SEL_FORMAT_TARGETS || (_atoms[i].formats & format)) - { - ecore_x_dnd_type_set(xwin, _atoms[i].name, EINA_TRUE); - cnp_debug("set dnd type: %s\n", _atoms[i].name); - } - } - - sel = _x11_selections + ELM_SEL_TYPE_XDND; - sel->active = EINA_TRUE; - sel->widget = obj; - sel->format = format; - sel->selbuf = data ? strdup(data) : NULL; - sel->action = action; - dragwidget = obj; - dragaction = action; - - evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, - _x11_drag_target_del, obj); - /* TODO BUG: should NEVER have these as globals! They should be per context (window). */ - dragposcb = dragpos; - dragposdata = dragdata; - dragacceptcb = acceptcb; - dragacceptdata = acceptdata; - dragdonecb = dragdone; - dragdonedata = donecbdata; - /* TODO BUG: should increase dnd-awareness, in case it's drop target as well. See _x11_drag_mouse_up() */ - ecore_x_dnd_aware_set(xwin, EINA_TRUE); - ecore_x_dnd_callback_pos_update_set(_x11_drag_move, NULL); - ecore_x_dnd_self_begin(xwin, (unsigned char *)&xdnd, sizeof(Elm_Sel_Type)); - actx = _x11_dnd_action_rev_map(dragaction); - ecore_x_dnd_source_action_set(actx); - ecore_x_pointer_grab(xwin); - handler_up = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP, - _x11_drag_mouse_up, - (void *)(long)xwin); - handler_status = ecore_event_handler_add(ECORE_X_EVENT_XDND_STATUS, - _x11_dnd_status, NULL); - dragwin = elm_win_add(NULL, "Elm-Drag", ELM_WIN_DND); - elm_win_alpha_set(dragwin, EINA_TRUE); - elm_win_override_set(dragwin, EINA_TRUE); - xdragwin = _x11_elm_widget_xwin_get(dragwin); - ecore_x_window_ignore_set(xdragwin, 1); - - /* dragwin has to be rotated as the main window is */ - if (elm_widget_is(obj)) - { - Evas_Object *win = elm_widget_top_get(obj); - if (win && efl_isa(win, EFL_UI_WIN_CLASS)) - { - elm_win_rotation_set(dragwin, elm_win_rotation_get(win)); - efl_event_callback_add(win, EFL_UI_WIN_EVENT_ROTATION_CHANGED, _x11_win_rotation_changed_cb, dragwin); - } - } - - if (createicon) - { - Evas_Coord xoff = 0, yoff = 0; - - icon = createicon(createdata, dragwin, &xoff, &yoff); - if (icon) - { - x2 = xoff; - y2 = yoff; - evas_object_geometry_get(icon, NULL, NULL, &w, &h); - } - } - else - { - icon = elm_icon_add(dragwin); - evas_object_size_hint_weight_set(icon, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - // need to resize - } - elm_win_resize_object_add(dragwin, icon); - - /* Position subwindow appropriately */ - ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj)); - ecore_evas_geometry_get(ee, &ex, &ey, &ew, &eh); - evas_object_resize(dragwin, w, h); - - evas_object_show(icon); - evas_object_show(dragwin); - evas_pointer_canvas_xy_get(evas_object_evas_get(obj), &x3, &y3); - - rot = ecore_evas_rotation_get(ee); - switch (rot) - { - case 90: - xr = y3; - yr = ew - x3; - _dragx = y3 - y2; - _dragy = x3 - x2; - break; - case 180: - xr = ew - x3; - yr = eh - y3; - _dragx = x3 - x2; - _dragy = y3 - y2; - break; - case 270: - xr = eh - y3; - yr = x3; - _dragx = y3 - y2; - _dragy = x3 - x2; - break; - default: - xr = x3; - yr = y3; - _dragx = x3 - x2; - _dragy = y3 - y2; - break; - } - x = ex + xr - _dragx; - y = ey + yr - _dragy; - evas_object_move(dragwin, x, y); - dragwin_x_start = dragwin_x_end = x; - dragwin_y_start = dragwin_y_end = y; - - return EINA_TRUE; -} - -static Eina_Bool -_x11_elm_drag_action_set(Evas_Object *obj, Elm_Xdnd_Action action) -{ - Ecore_X_Atom actx; - - _x11_elm_cnp_init(); - if (!dragwin) return EINA_FALSE; - - if (dragwidget != obj) return EINA_FALSE; - if (dragaction == action) return EINA_TRUE; - dragaction = action; - actx = _x11_dnd_action_rev_map(dragaction); - ecore_x_dnd_source_action_set(actx); - return EINA_TRUE; -} - -static Eina_Bool -_x11_elm_selection_selection_has_owner(Evas_Object *obj EINA_UNUSED) -{ - _x11_elm_cnp_init(); - return !!ecore_x_selection_owner_get(ECORE_X_ATOM_SELECTION_CLIPBOARD); -} - -#endif - -#ifdef HAVE_ELEMENTARY_WL2 -struct _Wl_Cnp_Selection -{ - char *selbuf; - int buflen; - - Evas_Object *widget; - Evas_Object *requestwidget; - - void *udata; - Elm_Sel_Type seltype; - Elm_Sel_Format requestformat; - Elm_Drop_Cb datacb; - - Elm_Selection_Loss_Cb loss_cb; - void *loss_data; - - Elm_Sel_Format format; - Ecore_Wl2_Window *win; - Elm_Xdnd_Action action; - uint32_t selection_serial; - uint32_t drag_serial; - - Eina_Bool active : 1; -}; - -static Eina_Bool _wl_elm_cnp_init(void); - -static Wl_Cnp_Selection wl_cnp_selection = -{ - 0, 0, NULL, NULL, - NULL, 0, 0, NULL, NULL, NULL, - 0, NULL, 0, EINA_FALSE -}; - -static void _wl_sel_obj_del2(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED); -static Eina_Bool _wl_elm_cnp_selection_set(Evas_Object *obj EINA_UNUSED, Elm_Sel_Type selection, Elm_Sel_Format format EINA_UNUSED, const void *selbuf, size_t buflen); -static Eina_Bool _wl_elm_cnp_selection_get(const Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format EINA_UNUSED, Elm_Drop_Cb datacb EINA_UNUSED, void *udata EINA_UNUSED); -static Eina_Bool _wl_elm_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type selection); - -static Eina_Bool _wl_selection_send(void *udata, int type EINA_UNUSED, void *event); -static Eina_Bool _wl_selection_receive(void *udata, int type EINA_UNUSED, void *event); - -static Eina_Bool _wl_elm_dnd_init(void); -static Eina_Bool _wl_elm_drop_target_add(Evas_Object *obj, Elm_Sel_Format format, Elm_Drag_State entercb, void *enterdata, Elm_Drag_State leavecb, void *leavedata, Elm_Drag_Pos poscb, void *posdata, Elm_Drop_Cb dropcb, void *dropdata); -static Eina_Bool _wl_elm_drop_target_del(Evas_Object *obj, Elm_Sel_Format format, Elm_Drag_State entercb, void *enterdata, Elm_Drag_State leavecb, void *leavedata, Elm_Drag_Pos poscb, void *posdata, Elm_Drop_Cb dropcb, void *dropdata); - -static Eina_Bool _wl_elm_drag_action_set(Evas_Object *obj, Elm_Xdnd_Action action); -static Eina_Bool _wl_elm_drag_start(Evas_Object *obj, Elm_Sel_Format format, const char *data, Elm_Xdnd_Action action, Elm_Drag_Icon_Create_Cb createicon, void *createdata, Elm_Drag_Pos dragpos, void *dragdata, Elm_Drag_Accept acceptcb, void *acceptdata, Elm_Drag_State dragdone, void *donecbdata); - -static void _wl_drag_source_del(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event EINA_UNUSED); - -static Eina_Bool _wl_dnd_enter(void *data EINA_UNUSED, int type EINA_UNUSED, void *event); -static Eina_Bool _wl_dnd_leave(void *data EINA_UNUSED, int type EINA_UNUSED, void *event); -static Eina_Bool _wl_dnd_position(void *data EINA_UNUSED, int type EINA_UNUSED, void *event); -static Eina_Bool _wl_dnd_drop(void *data EINA_UNUSED, int type EINA_UNUSED, void *event); -/* static Eina_Bool _wl_dnd_offer(void *data EINA_UNUSED, int type EINA_UNUSED, void *event); */ - -static Eina_Bool _wl_dnd_receive(void *data, int type EINA_UNUSED, void *event); -static Eina_Bool _wl_dnd_end(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED); -static void _wl_dropable_data_handle(Wl_Cnp_Selection *sel, Ecore_Wl2_Event_Offer_Data_Ready *ev); - -static Dropable *_wl_dropable_find(unsigned int win); -static void _wl_dropable_handle(Dropable *drop, Evas_Coord x, Evas_Coord y); -static void _wl_dropable_all_clean(unsigned int win); -static Eina_Bool _wl_drops_accept(const char *type); -static Ecore_Wl2_Window *_wl_elm_widget_window_get(const Evas_Object *obj); -static Evas * _wl_evas_get_from_win(unsigned int win); - -static Eina_Bool -_wl_is_uri_type_data(const char *data, int len) -{ - char *p; - if (len < 6) return EINA_FALSE; - - p = (char *)data; - if (!p) return EINA_FALSE; - if (strncmp(p, "file:/", 6)) - { - if (*p != '/') return EINA_FALSE; - } - return EINA_TRUE; -} - -static Eina_Bool -_wl_targets_converter(char *target, Wl_Cnp_Selection *sel EINA_UNUSED, void *data EINA_UNUSED, int size EINA_UNUSED, void **data_ret, int *size_ret) -{ - cnp_debug("in\n"); - if (!data_ret) return EINA_FALSE; - - const char *sep = "\n"; - char *aret; - int len = 0; - int i = 0; - Elm_Sel_Format formats = ELM_SEL_FORMAT_NONE; - Eina_Bool is_uri = EINA_FALSE; - - if (sel->format) - { - formats = sel->format; - is_uri = _wl_is_uri_type_data(sel->selbuf, sel->buflen); - } - else - { - Cnp_Atom *atom = eina_hash_find(_types_hash, target); - if (atom) - formats = atom->formats; - } - for (i = 0; i < CNP_N_ATOMS; i++) - { - if (formats & _atoms[i].formats) - { - if ((is_uri) || - ((!is_uri) && strcmp(_atoms[i].name, "text/uri-list"))) - len += strlen(_atoms[i].name) + strlen(sep); - } - } - len++; //terminating null byte - aret = calloc(1, len * sizeof(char)); - if (!aret) return EINA_FALSE; - for (i = 0; i < CNP_N_ATOMS; i++) - { - if (formats & _atoms[i].formats) - { - if ((is_uri) || - ((!is_uri) && strcmp(_atoms[i].name, "text/uri-list"))) - { - aret = strcat(aret, _atoms[i].name); - aret = strcat(aret, sep); - } - } - } - *data_ret = aret; - if (size_ret) *size_ret = len; - - return EINA_TRUE; -} - -static Eina_Bool -_wl_general_converter(char *target, Wl_Cnp_Selection *sel EINA_UNUSED, void *data, int size, void **data_ret, int *size_ret) -{ - Elm_Sel_Format formats = ELM_SEL_FORMAT_NONE; - Cnp_Atom *atom = NULL; - - cnp_debug("in\n"); - - atom = eina_hash_find(_types_hash, target); - if (atom) - formats = atom->formats; - if (formats == ELM_SEL_FORMAT_NONE) - { - if (data_ret) - { - *data_ret = malloc(size * sizeof(char) + 1); - if (!*data_ret) return EINA_FALSE; - memcpy(*data_ret, data, size); - ((char**)(data_ret))[0][size] = 0; - } - if (size_ret) *size_ret = size; - } - else - { - if (data) - { - if (data_ret) *data_ret = strdup(data); - if (size_ret) *size_ret = strlen(data); - } - else - { - if (data_ret) *data_ret = NULL; - if (size_ret) *size_ret = 0; - } - } - - return EINA_TRUE; -} - -static Eina_Bool -_wl_text_converter(char *target, Wl_Cnp_Selection *sel, void *data, int size, void **data_ret, int *size_ret) -{ - Elm_Sel_Format formats = ELM_SEL_FORMAT_NONE; - Cnp_Atom *atom = NULL; - - cnp_debug("in\n"); - - atom = eina_hash_find(_types_hash, target); - if (atom) - formats = atom->formats; - if (formats == ELM_SEL_FORMAT_NONE) - { - if (data_ret) - { - *data_ret = malloc(size * sizeof(char) + 1); - if (!*data_ret) return EINA_FALSE; - memcpy(*data_ret, data, size); - ((char**)(data_ret))[0][size] = 0; - if (size_ret) *size_ret = size; - return EINA_TRUE; - } - } - else if ((formats & ELM_SEL_FORMAT_MARKUP) || - (formats & ELM_SEL_FORMAT_HTML)) - { - *data_ret = _elm_util_mkup_to_text(data); - if (size_ret && *data_ret) *size_ret = strlen(*data_ret); - } - else if (formats & ELM_SEL_FORMAT_TEXT) - { - *data_ret = strdup(data); - if (size_ret && *data_ret) *size_ret = strlen(*data_ret); - } - else if (formats & ELM_SEL_FORMAT_IMAGE) - { - cnp_debug("Image %s\n", evas_object_type_get(sel->widget)); - evas_object_image_file_get(elm_photocam_internal_image_get(sel->widget), - (const char **)data_ret, NULL); - if (!*data_ret) *data_ret = strdup("No file"); - else *data_ret = strdup(*data_ret); - - if (!*data_ret) - { - ERR("Failed to allocate memory!"); - *size_ret = 0; - return EINA_FALSE; - } - - if (size_ret) *size_ret = strlen(*data_ret); - } - return EINA_TRUE; -} - -static void -_wl_selection_parser(void *_data, int size, char ***ret_data, int *ret_count) -{ - char **files = NULL; - int num_files = 0; - char *data = NULL; - - data = malloc(size); - if (data && (size > 0)) - { - int i, is; - char *tmp; - char **t2; - - memcpy(data, _data, size); - if (data[size - 1]) - { - char *t; - - /* Isn't nul terminated */ - size++; - t = realloc(data, size); - if (!t) goto done; - data = t; - data[size - 1] = 0; - } - - tmp = malloc(size); - if (!tmp) goto done; - i = 0; - is = 0; - while ((is < size) && (data[is])) - { - if ((i == 0) && (data[is] == '#')) - for (; ((data[is]) && (data[is] != '\n')); is++) ; - else - { - if ((data[is] != '\r') && (data[is] != '\n')) - tmp[i++] = data[is++]; - else - { - while ((data[is] == '\r') || (data[is] == '\n')) - is++; - tmp[i] = 0; - num_files++; - t2 = realloc(files, num_files * sizeof(char *)); - if (t2) - { - files = t2; - files[num_files - 1] = strdup(tmp); - } - else - { - num_files--; - goto freetmp; - } - tmp[0] = 0; - i = 0; - } - } - } - if (i > 0) - { - tmp[i] = 0; - num_files++; - t2 = realloc(files, num_files * sizeof(char *)); - if (t2) - { - files = t2; - files[num_files - 1] = strdup(tmp); - } - else - { - num_files--; - goto freetmp; - } - } -freetmp: - free(tmp); - } -done: - free(data); - if (ret_data) *ret_data = files; - else - { - int i; - - for (i = 0; i < num_files; i++) free(files[i]); - free(files); - } - if (ret_count) *ret_count = num_files; -} - -static Eina_Bool -_wl_data_preparer_markup(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info EINA_UNUSED) -{ - cnp_debug("In\n"); - - ddata->format = ELM_SEL_FORMAT_MARKUP; - ddata->data = eina_memdup((unsigned char *)ev->data, ev->len, EINA_TRUE); - ddata->len = ev->len; - ddata->action = sel->action; - - return EINA_TRUE; -} - -static Eina_Bool -_wl_data_preparer_uri(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info EINA_UNUSED) -{ - char *p, *stripstr = NULL; - char *data = ev->data; - Dropable *drop; - const char *type = NULL; - - cnp_debug("In\n"); - - drop = efl_key_data_get(sel->requestwidget, "__elm_dropable"); - if (drop) type = drop->last.type; - - if ((type) && (!strcmp(type, "text/uri-list"))) - { - int num_files = 0; - char **files = NULL; - Efreet_Uri *uri; - Eina_Strbuf *strbuf; - int i; - - strbuf = eina_strbuf_new(); - if (!strbuf) return EINA_FALSE; - - _wl_selection_parser(ev->data, ev->len, &files, &num_files); - cnp_debug("got a files list\n"); - - for (i = 0; i < num_files; i++) - { - uri = efreet_uri_decode(files[i]); - if (uri) - { - eina_strbuf_append(strbuf, uri->path); - efreet_uri_free(uri); - } - else - { - eina_strbuf_append(strbuf, files[i]); - } - if (i < (num_files - 1)) - eina_strbuf_append(strbuf, "\n"); - free(files[i]); - } - free(files); - stripstr = eina_strbuf_string_steal(strbuf); - eina_strbuf_free(strbuf); - } - else - { - Efreet_Uri *uri; - - p = (char *)eina_memdup((unsigned char *)data, ev->len, EINA_TRUE); - if (!p) return EINA_FALSE; - uri = efreet_uri_decode(p); - if (!uri) - { - /* Is there any reason why we care of URI without scheme? */ - if (p[0] == '/') stripstr = p; - else free(p); - } - else - { - free(p); - stripstr = strdup(uri->path); - efreet_uri_free(uri); - } - } - - if (!stripstr) - { - cnp_debug("Couldn't find a file\n"); - return EINA_FALSE; - } - free(savedtypes.imgfile); - - ddata->data = stripstr; - ddata->len = strlen(stripstr); - ddata->action = sel->action; - ddata->format = sel->requestformat; - - return EINA_TRUE; -} - -static Eina_Bool -_wl_data_preparer_vcard(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info EINA_UNUSED) -{ - cnp_debug("In\n"); - - ddata->format = ELM_SEL_FORMAT_VCARD; - ddata->data = eina_memdup((unsigned char *)ev->data, ev->len, EINA_TRUE); - ddata->len = ev->len; - ddata->action = sel->action; - - return EINA_TRUE; -} - -static Eina_Bool -_wl_data_preparer_image(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info) -{ - cnp_debug("In\n"); - Tmp_Info *tmp; - int len = 0; - - tmp = _tempfile_new(ev->len); - if (!tmp) - return EINA_FALSE; - memcpy(tmp->map, ev->data, ev->len); - munmap(tmp->map, ev->len); - - len = strlen(tmp->filename); - ddata->format = ELM_SEL_FORMAT_IMAGE; - ddata->data = eina_memdup((unsigned char*)tmp->filename, len, EINA_TRUE); - ddata->len = len; - ddata->action = sel->action; - *tmp_info = tmp; - - return EINA_TRUE; -} - -static Eina_Bool -_wl_data_preparer_text(Wl_Cnp_Selection *sel, Elm_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info EINA_UNUSED) -{ - cnp_debug("In\n"); - - ddata->format = ELM_SEL_FORMAT_TEXT; - ddata->data = eina_memdup((unsigned char *)ev->data, ev->len, EINA_TRUE); - ddata->len = ev->len; - ddata->action = sel->action; - - return EINA_TRUE; -} - -static void -_wl_sel_obj_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) -{ - Wl_Cnp_Selection *sel = data; - if (sel->widget == obj) - { - sel->loss_cb = NULL; - sel->loss_data = NULL; - sel->widget = NULL; - } - if (dragwidget == obj) dragwidget = NULL; -} - -static Ecore_Wl2_Input * -_wl_default_seat_get(Ecore_Wl2_Window *win, Evas_Object *obj) -{ - Eo *seat, *parent2, *ewin; - - if (obj) - { - // FIXME (there might be a better solution): - // In case of inwin, we want to use the main wl2 window for cnp, but obj - // obj belongs to the buffer canvas, so the default seat for obj does not - // match the window win. - 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); - return input; - } - - seat = evas_default_device_get(evas_object_evas_get(obj), EFL_INPUT_DEVICE_TYPE_SEAT); - EINA_SAFETY_ON_NULL_RETURN_VAL(seat, NULL); - return ecore_wl2_display_input_find(ecore_wl2_window_display_get(win), - evas_device_seat_id_get(seat)); -} - -static void -_wl_sel_obj_del2(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) -{ - Wl_Cnp_Selection *sel = data; - if (sel->requestwidget == obj) sel->requestwidget = NULL; -} - -static Eina_Bool -_wl_elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, const void *selbuf, size_t buflen) -{ - Ecore_Wl2_Window *win; - Wl_Cnp_Selection *sel = &wl_cnp_selection; - - if ((!selbuf) && (format != ELM_SEL_FORMAT_IMAGE)) - return elm_object_cnp_selection_clear(obj, selection); - - if (buflen <= 0) - return EINA_FALSE; - - _wl_elm_cnp_init(); - - win = _wl_elm_widget_window_get(obj); - - if ((sel->widget != obj) && sel->loss_cb) - sel->loss_cb(sel->loss_data, selection); - - if (sel->widget) - evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL, - _wl_sel_obj_del, &wl_cnp_selection); - sel->active = EINA_TRUE; - sel->seltype = selection; - sel->widget = obj; - sel->win = win; - /* sel->set(win, &selection, sizeof(Elm_Sel_Type)); */ - sel->format = format; - sel->loss_cb = NULL; - sel->loss_data = NULL; - - evas_object_event_callback_add - (sel->widget, EVAS_CALLBACK_DEL, _wl_sel_obj_del, &wl_cnp_selection); - - if (selbuf) - { - int i = 0, count = 0; - Eina_Bool is_uri = EINA_FALSE; - const char **types; - - if (format & ELM_SEL_FORMAT_IMAGE) - { - /* FIXME */ - // selbuf is actual image data, not text/string - sel->selbuf = malloc(buflen + 1); - if (!sel->selbuf) - { - elm_object_cnp_selection_clear(obj, selection); - return EINA_FALSE; - } - memcpy(sel->selbuf, selbuf, buflen); - sel->selbuf[buflen] = 0; - } - else - { - free(sel->selbuf); - sel->buflen = buflen; - sel->selbuf = strdup((char*)selbuf); - } - - is_uri = _wl_is_uri_type_data(selbuf, buflen); - types = malloc(sizeof(char *)); - if (!types) return EINA_FALSE; - for (i = 0, count = 1; i < CNP_N_ATOMS; i++) - { - if (format & _atoms[i].formats) - { - if ((is_uri) || - ((!is_uri) && strcmp(_atoms[i].name, "text/uri-list"))) - { - const char **t = NULL; - - types[count - 1] = _atoms[i].name; - count++; - t = realloc(types, sizeof(char *) * count); - if (!t) - { - free(types); - return EINA_FALSE; - } - types = t; - } - } - } - types[count - 1] = 0; - - sel->selection_serial = ecore_wl2_dnd_selection_set(_wl_default_seat_get(win, obj), types); - - free(types); - return _local_elm_cnp_selection_set(obj, selection, format, selbuf, buflen); - } - else - { - sel->selbuf = NULL; - } - - return EINA_FALSE; -} - - -static Elm_Xdnd_Action -_wl_to_elm(Ecore_Wl2_Drag_Action action) -{ - #define CONV(wl, elm) if (action == wl) return elm; - CONV(ECORE_WL2_DRAG_ACTION_COPY, ELM_XDND_ACTION_COPY); - CONV(ECORE_WL2_DRAG_ACTION_MOVE, ELM_XDND_ACTION_MOVE); - CONV(ECORE_WL2_DRAG_ACTION_ASK, ELM_XDND_ACTION_ASK); - #undef CONV - return ELM_XDND_ACTION_UNKNOWN; -} - -typedef struct { - Ecore_Wl2_Offer *offer; - - Evas_Object *requestwidget; - Elm_Drop_Cb drop_cb; - void *drop_cb_data; - Elm_Sel_Format format; - - Ecore_Event_Handler *handler; -} Selection_Ready; - -static void -_wl_selection_receive_timeout(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) -{ - Selection_Ready *ready = data; - - if (ready->requestwidget != obj) return; - - ecore_event_handler_del(ready->handler); - free(ready); -} - -static Eina_Bool -_wl_selection_receive(void *data, int type EINA_UNUSED, void *event) -{ - Ecore_Wl2_Event_Offer_Data_Ready *ev = event; - Selection_Ready *ready = data; - - if (ready->offer != ev->offer) return ECORE_CALLBACK_PASS_ON; - - if (ready->drop_cb) - { - Elm_Selection_Data sdata; - - sdata.x = sdata.y = 0; - sdata.format = ready->format; - sdata.data = ev->data; - sdata.len = ev->len; - sdata.action = _wl_to_elm(ecore_wl2_offer_action_get(ready->offer)); - ready->drop_cb(ready->drop_cb_data, - ready->requestwidget, - &sdata); - } - else - { - char *stripstr, *mkupstr; - - stripstr = malloc(ev->len + 1); - if (!stripstr) return ECORE_CALLBACK_CANCEL; - strncpy(stripstr, (char *)ev->data, ev->len); - stripstr[ev->len] = '\0'; - mkupstr = _elm_util_text_to_mkup((const char *)stripstr); - /* TODO BUG: should never NEVER assume it's an elm_entry! */ - _elm_entry_entry_paste(ready->requestwidget, mkupstr); - free(stripstr); - free(mkupstr); - } - - evas_object_event_callback_del_full(ready->requestwidget, - EVAS_CALLBACK_DEL, - _wl_selection_receive_timeout, ready); - - ecore_event_handler_del(ready->handler); - free(data); - return ECORE_CALLBACK_CANCEL; -} - -typedef struct _Format_Translation{ - Elm_Sel_Format format; - char **translates; -}Format_Translation; - -char *markup[] = {"application/x-elementary-markup", "", NULL}; -char *text[] = {"text/plain;charset=utf-8", "text/plain", NULL}; -char *html[] = {"text/html;charset=utf-8", "text/html", NULL}; -char *vcard[] = {"text/x-vcard", NULL}; -char *image[] = {"image/", "text/uri-list", NULL}; - -Format_Translation convertion[] = { - {ELM_SEL_FORMAT_MARKUP, markup}, - {ELM_SEL_FORMAT_TEXT, text}, - {ELM_SEL_FORMAT_HTML, html}, - {ELM_SEL_FORMAT_VCARD, vcard}, - {ELM_SEL_FORMAT_IMAGE, image}, - {ELM_SEL_FORMAT_NONE, NULL}, -}; - -static Eina_Bool -_wl_elm_cnp_selection_get(const Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata) -{ - Ecore_Wl2_Window *win; - Ecore_Wl2_Input *input; - Ecore_Wl2_Offer *offer; - int i = 0; - //Wl_Cnp_Selection *sel = &wl_cnp_selection; - - _wl_elm_cnp_init(); - - if (selection == ELM_SEL_TYPE_XDND) return EINA_FALSE; - - //if (sel->active) - //return _local_elm_cnp_selection_get(obj, selection, format, datacb, udata); - win = _wl_elm_widget_window_get(obj); - - input = _wl_default_seat_get(win, (void*)obj); - offer = ecore_wl2_dnd_selection_get(input); - - //there can be no selection available - if (!offer) return EINA_FALSE; - - for (i = 0; convertion[i].translates; i++) - { - int j = 0; - if (!(format & convertion[i].format)) continue; - - for (j = 0; convertion[i].translates[j]; j++) - { - if (!ecore_wl2_offer_supports_mime(offer, convertion[i].translates[j])) continue; - - //we have found mathing mimetypes - Selection_Ready *ready; - - ready = calloc(1, sizeof(Selection_Ready)); - - ready->requestwidget = (Evas_Object *) obj; - ready->drop_cb = datacb; - ready->drop_cb_data = udata; - ready->offer = offer; - ready->format = convertion[i].format; - - evas_object_event_callback_add(ready->requestwidget, EVAS_CALLBACK_DEL, - _wl_selection_receive_timeout, ready); - ready->handler = ecore_event_handler_add(ECORE_WL2_EVENT_OFFER_DATA_READY, _wl_selection_receive, ready); - - ecore_wl2_offer_receive(offer, (char*)convertion[i].translates[j]); - return EINA_TRUE; - } - } - - return EINA_FALSE; -} - -static void -_wl_elm_cnp_selection_loss_callback_set(Evas_Object *obj EINA_UNUSED, Elm_Sel_Type selection EINA_UNUSED, Elm_Selection_Loss_Cb func, const void *data) -{ - Wl_Cnp_Selection *sel = &wl_cnp_selection; - - _wl_elm_cnp_init(); - - sel->loss_cb = func; - sel->loss_data = (void *)data; -} - -static Eina_Bool -_wl_elm_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type selection EINA_UNUSED) -{ - Wl_Cnp_Selection *sel = &wl_cnp_selection; - - _wl_elm_cnp_init(); - - if ((!sel->active) || (sel->widget != obj)) - return EINA_TRUE; - - if (sel->widget) - evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL, - _wl_sel_obj_del, &wl_cnp_selection); - if (sel->requestwidget) - evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL, - _wl_sel_obj_del2, &wl_cnp_selection); - - sel->widget = NULL; - sel->requestwidget = NULL; - sel->loss_cb = NULL; - sel->loss_data = NULL; - - sel->active = EINA_FALSE; - ELM_SAFE_FREE(sel->selbuf, free); - sel->buflen = 0; - /* sel->clear(); */ - sel->selection_serial = ecore_wl2_dnd_selection_clear(_wl_default_seat_get(_wl_elm_widget_window_get(obj), obj)); - - return _local_elm_object_cnp_selection_clear(obj, selection); -} - -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 EINA_UNUSED, int type EINA_UNUSED, void *event) -{ - Elm_Cnp_Event_Selection_Changed *e; - Ecore_Wl2_Event_Seat_Selection *ev = event; - Ecore_Wl2_Input *seat; - - seat = ecore_wl2_display_input_find(ev->display, ev->seat); - EINA_SAFETY_ON_NULL_RETURN_VAL(seat, ECORE_CALLBACK_RENEW); - e = calloc(1, sizeof(Elm_Cnp_Event_Selection_Changed)); - EINA_SAFETY_ON_NULL_RETURN_VAL(e, ECORE_CALLBACK_RENEW); - e->type = ELM_SEL_TYPE_CLIPBOARD; - e->seat_id = ev->seat; - /* connect again to add ref */ - e->display = ecore_wl2_display_connect(ecore_wl2_display_name_get(ev->display)); - e->exists = !!ecore_wl2_dnd_selection_get(seat); - ecore_event_add(ELM_CNP_EVENT_SELECTION_CHANGED, e, _wl_selection_changed_free, ev->display); - return ECORE_CALLBACK_RENEW; -} - -static Eina_Bool -_wl_selection_send(void *data, int type EINA_UNUSED, void *event) -{ - char *buf; - int ret, len_remained; - int len_written = 0; - Wl_Cnp_Selection *sel; - Ecore_Wl2_Event_Data_Source_Send *ev; - void *data_ret = NULL; - int len_ret = 0; - int i = 0; - - _wl_elm_cnp_init(); - cnp_debug("In\n"); - ev = event; - sel = data; - if ((ev->serial != sel->selection_serial) && - (ev->serial != sel->drag_serial)) - return ECORE_CALLBACK_RENEW; - - for (i = 0; i < CNP_N_ATOMS; i++) - { - if (!strcmp(_atoms[i].name, ev->type)) - { - cnp_debug("Found a type: %s\n", _atoms[i].name); - Dropable *drop; - drop = efl_key_data_get(sel->requestwidget, "__elm_dropable"); - if (drop) - drop->last.type = _atoms[i].name; - if (_atoms[i].wl_converter) - { - _atoms[i].wl_converter(ev->type, sel, sel->selbuf, - sel->buflen, &data_ret, &len_ret); - } - else - { - data_ret = strdup(sel->selbuf); - len_ret = sel->buflen; - } - break; - } - } - - len_remained = len_ret; - buf = data_ret; - cnp_debug("write: %s", buf); - - while (len_written < len_ret) - { - ret = write(ev->fd, buf, len_remained); - if (ret == -1) break; - buf += ret; - len_written += ret; - len_remained -= ret; - } - free(data_ret); - - close(ev->fd); - return ECORE_CALLBACK_PASS_ON; -} - -static Eina_Bool -_wl_elm_cnp_init(void) -{ - static int _init_count = 0; - - if (_init_count > 0) return EINA_TRUE; - _init_count++; - - ecore_event_handler_add(ECORE_WL2_EVENT_DATA_SOURCE_SEND, - _wl_selection_send, &wl_cnp_selection); - ecore_event_handler_add(ECORE_WL2_EVENT_SEAT_SELECTION, - _wl_selection_changed, NULL); - return EINA_TRUE; -} - -static Eina_Bool -_wl_elm_dnd_init(void) -{ - static int _init_count = 0; - - if (_init_count > 0) return EINA_TRUE; - _init_count++; - - text_uri = eina_stringshare_add("text/uri-list"); - - _wl_elm_cnp_init(); - ecore_event_handler_add(ECORE_WL2_EVENT_DATA_SOURCE_END, - _wl_dnd_end, &wl_cnp_selection); - - return EINA_TRUE; -} - -static Eina_Bool -_wl_elm_drop_target_add(Evas_Object *obj, Elm_Sel_Format format, Elm_Drag_State entercb, void *enterdata, Elm_Drag_State leavecb, void *leavedata, Elm_Drag_Pos poscb, void *posdata, Elm_Drop_Cb dropcb, void *dropdata) -{ - Dropable *dropable = NULL; - Dropable_Cbs *cbs = NULL; - - Eina_Bool first = !drops; - - cbs = calloc(1, sizeof(*cbs)); - if (!cbs) return EINA_FALSE; - - cbs->entercb = entercb; - cbs->enterdata = enterdata; - cbs->leavecb = leavecb; - cbs->leavedata = leavedata; - cbs->poscb = poscb; - cbs->posdata = posdata; - cbs->dropcb = dropcb; - cbs->dropdata = dropdata; - cbs->types = format; - - dropable = efl_key_data_get(obj, "__elm_dropable"); - if (!dropable) - { - /* Create new drop */ - dropable = calloc(1, sizeof(Dropable)); - if (!dropable) goto error; - drops = eina_list_append(drops, dropable); - if (!drops) goto error; - dropable->obj = obj; - efl_key_data_set(obj, "__elm_dropable", dropable); - } - - dropable->cbs_list = - eina_inlist_append(dropable->cbs_list, EINA_INLIST_GET(cbs)); - - evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, - _all_drop_targets_cbs_del, obj); - - if (first) - { - handler_enter = - ecore_event_handler_add(ECORE_WL2_EVENT_DND_ENTER, - _wl_dnd_enter, NULL); - handler_leave = - ecore_event_handler_add(ECORE_WL2_EVENT_DND_LEAVE, - _wl_dnd_leave, NULL); - handler_pos = - ecore_event_handler_add(ECORE_WL2_EVENT_DND_MOTION, - _wl_dnd_position, NULL); - handler_drop = - ecore_event_handler_add(ECORE_WL2_EVENT_DND_DROP, - _wl_dnd_drop, NULL); - _wl_elm_dnd_init(); - } - - return EINA_TRUE; -error: - free(cbs); - free(dropable); - return EINA_FALSE; -} - -static Eina_Bool -_wl_elm_drop_target_del(Evas_Object *obj, Elm_Sel_Format format, - Elm_Drag_State entercb, void *enterdata, - Elm_Drag_State leavecb, void *leavedata, - Elm_Drag_Pos poscb, void *posdata, - Elm_Drop_Cb dropcb, void *dropdata) -{ - - if (!_local_elm_drop_target_del(obj, format, entercb, enterdata, - leavecb, leavedata, poscb, posdata, dropcb, dropdata)) - { - return EINA_FALSE; - } - - if (!drops) - { - ELM_SAFE_FREE(handler_pos, ecore_event_handler_del); - ELM_SAFE_FREE(handler_drop, ecore_event_handler_del); - ELM_SAFE_FREE(handler_enter, ecore_event_handler_del); - ELM_SAFE_FREE(handler_leave, ecore_event_handler_del); - } - - return EINA_TRUE; -} - -static Eina_Bool -_wl_elm_drag_action_set(Evas_Object *obj, Elm_Xdnd_Action action) -{ - if (!dragwin) return EINA_FALSE; - if (dragwidget != obj) return EINA_FALSE; - if (dragaction == action) return EINA_TRUE; - dragaction = action; - return EINA_TRUE; -} - -static Eina_Bool -_wl_elm_drag_start(Evas_Object *obj, Elm_Sel_Format format, const char *data, - Elm_Xdnd_Action action, - Elm_Drag_Icon_Create_Cb createicon, void *createdata, - Elm_Drag_Pos dragpos, void *dragdata, - Elm_Drag_Accept acceptcb, void *acceptdata, - Elm_Drag_State dragdone, void *donecbdata) -{ - Ecore_Evas *ee; - Evas_Object *icon = NULL; - int x, y, x2 = 0, y2 = 0, x3, y3, w = 0, h = 0; - const char *types[CNP_N_ATOMS + 1]; - int i, nb_types = 0; - Ecore_Wl2_Window *parent = NULL, *win; - - _wl_elm_dnd_init(); - - /* if we already have a drag, get out */ - if (dragwin) return EINA_FALSE; - - for (i = CNP_ATOM_LISTING_ATOMS + 1; i < CNP_N_ATOMS; i++) - { - if (format == ELM_SEL_FORMAT_TARGETS || (_atoms[i].formats & format)) - { - types[nb_types++] = _atoms[i].name; - cnp_debug("set dnd type: %s\n", _atoms[i].name); - } - } - types[nb_types] = NULL; - - win = _wl_elm_widget_window_get(obj); - ecore_wl2_dnd_drag_types_set(_wl_default_seat_get(win, obj), types); - - /* set the drag data used when a drop occurs */ - free(wl_cnp_selection.selbuf); - wl_cnp_selection.buflen = 0; - wl_cnp_selection.selbuf = eina_strdup(data); - - if (data) - { - wl_cnp_selection.buflen = strlen(wl_cnp_selection.selbuf); - } - - /* setup callback to notify if this object gets deleted */ - evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, - _wl_drag_source_del, obj); - - dragwidget = obj; - dragaction = action; - dragposcb = dragpos; - dragposdata = dragdata; - dragacceptcb = acceptcb; - dragacceptdata = acceptdata; - dragdonecb = dragdone; - dragdonedata = donecbdata; - - dragwin = elm_win_add(NULL, "Elm-Drag", ELM_WIN_DND); - elm_win_alpha_set(dragwin, EINA_TRUE); - elm_win_borderless_set(dragwin, EINA_TRUE); - elm_win_override_set(dragwin, EINA_TRUE); - - win = elm_win_wl_window_get(dragwin); - - if (createicon) - { - Evas_Coord xoff = 0, yoff = 0; - - icon = createicon(createdata, dragwin, &xoff, &yoff); - if (icon) - { - x2 = xoff; - y2 = yoff; - evas_object_geometry_get(icon, NULL, NULL, &w, &h); - } - } - else - { - icon = elm_icon_add(dragwin); - evas_object_size_hint_weight_set(icon, EVAS_HINT_EXPAND, - EVAS_HINT_EXPAND); - } - - elm_win_resize_object_add(dragwin, icon); - evas_object_show(icon); - - /* Position subwindow appropriately */ - ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj)); - ecore_evas_geometry_get(ee, &x, &y, NULL, NULL); - x += x2; - y += y2; - dragwin_x_start = dragwin_x_end = x; - dragwin_y_start = dragwin_y_end = y; - - evas_object_move(dragwin, x, y); - evas_object_resize(dragwin, w, h); - evas_object_show(dragwin); - - evas_pointer_canvas_xy_get(evas_object_evas_get(obj), &x3, &y3); - _dragx = x3 - x2; - _dragy = y3 - y2; - - if (elm_widget_is(obj)) - { - Evas_Object *top; - - 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))) - parent = elm_win_wl_window_get(top); - } - if (!parent) - { - Evas *evas; - - if (!(evas = evas_object_evas_get(obj))) - return EINA_FALSE; - if (!(ee = ecore_evas_ecore_evas_get(evas))) - return EINA_FALSE; - - parent = ecore_evas_wayland2_window_get(ee); - } - - wl_cnp_selection.drag_serial = ecore_wl2_dnd_drag_start(_wl_default_seat_get(win, obj), parent, win); - - return EINA_TRUE; -} - -static void -_wl_drag_source_del(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event EINA_UNUSED) -{ - if (dragwidget == obj) - dragwidget = NULL; -} - -static Eina_Bool -_wl_dnd_enter(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) -{ - Ecore_Wl2_Event_Dnd_Enter *ev; - Eina_Array *known, *available; - unsigned int i = 0; - - ev = event; - - available = ecore_wl2_offer_mimes_get(ev->offer); - - free(savedtypes.types); - - savedtypes.ntypes = eina_array_count(available); - savedtypes.types = malloc(sizeof(char *) * savedtypes.ntypes); - if (!savedtypes.types) return EINA_FALSE; - - known = eina_array_new(5); - - for (i = 0; i < eina_array_count(available); i++) - { - savedtypes.types[i] = - eina_stringshare_add(eina_array_data_get(available, i)); - if (savedtypes.types[i] == text_uri) - { - savedtypes.textreq = 1; - ELM_SAFE_FREE(savedtypes.imgfile, free); - } - } - - doaccept = EINA_FALSE; - for (i = 0; i < eina_array_count(available); i++) - { - if (_wl_drops_accept(eina_array_data_get(available, i))) - { - eina_array_push(known, strdup(eina_array_data_get(available, i))); - } - } - - ecore_wl2_offer_mimes_set(ev->offer, known); - - return ECORE_CALLBACK_PASS_ON; -} - -static Eina_Bool -_wl_dnd_leave(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) -{ - Ecore_Wl2_Event_Dnd_Leave *ev; - Dropable *drop; - cnp_debug("In\n"); - - ev = event; - if ((drop = _wl_dropable_find(ev->win))) - { - _wl_dropable_handle(NULL, 0, 0); - _wl_dropable_all_clean(ev->win); - } - - return ECORE_CALLBACK_PASS_ON; -} - -static Eina_Bool -_wl_dnd_position(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) -{ - Ecore_Wl2_Event_Dnd_Motion *ev; - Dropable *drop; - Eina_Bool will_accept = EINA_FALSE; - - ev = event; - - cnp_debug("mouse pos %i %i\n", ev->x, ev->y); - - dragwin_x_end = ev->x - _dragx; - dragwin_y_end = ev->y - _dragy; - - drop = _wl_dropable_find(ev->win); - - if (drop) - { - Evas_Coord x = 0, y = 0; - Evas *evas = NULL; - Eina_List *dropable_list = NULL; - - x = ev->x; - y = ev->y; - _dropable_coords_adjust(drop, &x, &y); - evas = _wl_evas_get_from_win(ev->win); - if (evas) - dropable_list = _dropable_list_geom_find(evas, x, y); - - /* check if there is dropable (obj) can accept this drop */ - if (dropable_list) - { - Elm_Sel_Format saved_format; - Eina_List *l; - Eina_Bool found = EINA_FALSE; - Dropable *dropable = NULL; - - saved_format = - _dnd_types_to_format(savedtypes.types, savedtypes.ntypes); - - EINA_LIST_FOREACH(dropable_list, l, dropable) - { - Dropable_Cbs *cbs; - Eina_Inlist *itr; - - EINA_INLIST_FOREACH_SAFE(dropable->cbs_list, itr, cbs) - { - Elm_Sel_Format common_fmt = saved_format & cbs->types; - - if (common_fmt) - { - /* We found a target that can accept this type of data */ - int i, min_index = CNP_N_ATOMS; - - /* We have to find the first atom that corresponds to one - * of the supported data types. */ - for (i = 0; i < savedtypes.ntypes; i++) - { - Cnp_Atom *atom; - - atom = eina_hash_find(_types_hash, - savedtypes.types[i]); - if (atom && (atom->formats & common_fmt)) - { - int atom_idx = (atom - _atoms); - - if (min_index > atom_idx) - min_index = atom_idx; - } - } - if (min_index != CNP_N_ATOMS) - { - cnp_debug("Found atom %s\n", _atoms[min_index].name); - found = EINA_TRUE; - dropable->last.type = _atoms[min_index].name; - dropable->last.format = common_fmt; - break; - } - } - } - if (found) break; - } - if (found) - { - Evas_Coord ox = 0, oy = 0; - - evas_object_geometry_get(dropable->obj, &ox, &oy, NULL, NULL); - - cnp_debug("Candidate %p (%s)\n", - dropable->obj, efl_class_name_get(efl_class_get(dropable->obj))); - _wl_dropable_handle(dropable, x - ox, y - oy); - wl_cnp_selection.requestwidget = dropable->obj; - will_accept = EINA_TRUE; - } - else - { - //if not: send false status - cnp_debug("dnd position (%d, %d) not in obj\n", x, y); - _wl_dropable_handle(NULL, 0, 0); - // CCCCCCC: call dnd exit on last obj - } - eina_list_free(dropable_list); - } - } - - doaccept = will_accept; - - if (dragacceptcb) - dragacceptcb(dragacceptdata, wl_cnp_selection.requestwidget, will_accept); - - return ECORE_CALLBACK_PASS_ON; -} - -static Eina_Bool -_wl_dnd_receive(void *data, int type EINA_UNUSED, void *event) -{ - Ecore_Wl2_Event_Offer_Data_Ready *ev; - Ecore_Wl2_Offer *offer; - cnp_debug("In\n"); - - ev = event; - offer = data; - - if (offer != ev->offer) return ECORE_CALLBACK_PASS_ON; - - if (wl_cnp_selection.requestwidget) - { - Ecore_Wl2_Drag_Action action; - - action = ecore_wl2_offer_action_get(ev->offer); - if (action == ECORE_WL2_DRAG_ACTION_ASK) - ecore_wl2_offer_actions_set(ev->offer, ECORE_WL2_DRAG_ACTION_COPY, ECORE_WL2_DRAG_ACTION_COPY); - action = ecore_wl2_offer_action_get(ev->offer); - - wl_cnp_selection.action = _wl_to_elm(action); - - _wl_dropable_data_handle(&wl_cnp_selection, ev); - evas_object_event_callback_del_full(wl_cnp_selection.requestwidget, - EVAS_CALLBACK_DEL, - _wl_sel_obj_del2, &wl_cnp_selection); - wl_cnp_selection.requestwidget = NULL; - - } - - ecore_wl2_offer_finish(ev->offer); - - return ECORE_CALLBACK_CANCEL; -} - -static Eina_Bool -_wl_dnd_drop(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) -{ - Ecore_Wl2_Event_Dnd_Drop *ev; - Ecore_Wl2_Window *win; - Dropable *drop; - Eina_List *l; - - cnp_debug("In\n"); - ev = event; - savedtypes.x = ev->x; - savedtypes.y = ev->y; - - EINA_LIST_FOREACH(drops, l, drop) - { - if (drop->last.in) - { - cnp_debug("Request data of type %s\n", drop->last.type); - wl_cnp_selection.requestwidget = drop->obj; - wl_cnp_selection.requestformat = drop->last.format; - evas_object_event_callback_add(wl_cnp_selection.requestwidget, - EVAS_CALLBACK_DEL, _wl_sel_obj_del2, - &wl_cnp_selection); - - win = _wl_elm_widget_window_get(drop->obj); - ecore_wl2_offer_receive(ev->offer, (char*)drop->last.type); - ecore_event_handler_add(ECORE_WL2_EVENT_OFFER_DATA_READY, _wl_dnd_receive, ev->offer); - - return ECORE_CALLBACK_PASS_ON; - } - } - - win = ecore_wl2_display_window_find(_elm_wl_display, ev->win); - ecore_wl2_dnd_drag_end(_wl_default_seat_get(win, NULL)); - return ECORE_CALLBACK_PASS_ON; -} - -static Eina_Bool -_wl_dnd_end(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) -{ - Ecore_Wl2_Event_Data_Source_End *ev; - Ecore_Wl2_Window *win; - - cnp_debug("In\n"); - - ev = event; - if (ev->serial != wl_cnp_selection.drag_serial) - return ECORE_CALLBACK_RENEW; - if (dragdonecb) dragdonecb(dragdonedata, dragwidget); - - if (dragwin) - { - if (!doaccept) - { - /* Commit animation when drag cancelled */ - /* Record final position of dragwin, then do animation */ - ecore_animator_timeline_add(0.3, _drag_cancel_animate, dragwin); - } - else - { - /* No animation drop was committed */ - evas_object_del(dragwin); - } - dragwin = NULL; /* if not freed here, free in end of anim */ - } - - dragdonecb = NULL; - dragacceptcb = NULL; - dragposcb = NULL; - dragwidget = NULL; - doaccept = EINA_FALSE; - - win = ecore_wl2_display_window_find(_elm_wl_display, ev->win); - ecore_wl2_input_ungrab(_wl_default_seat_get(win, NULL)); - - return ECORE_CALLBACK_PASS_ON; -} - -static void -_wl_dropable_data_handle(Wl_Cnp_Selection *sel, Ecore_Wl2_Event_Offer_Data_Ready *ev) -{ - Dropable *drop; - Ecore_Wl2_Window *win; - - cnp_debug("In\n"); - drop = efl_key_data_get(sel->requestwidget, "__elm_dropable"); - if (drop) - { - Cnp_Atom *atom = NULL; - - atom = eina_hash_find(_types_hash, drop->last.type); - if (atom && atom->wl_data_preparer) - { - Elm_Selection_Data ddata; - Tmp_Info *tmp_info = NULL; - Eina_Bool success; - ddata.data = NULL; - - cnp_debug("Call notify for: %s\n", atom->name); - success = atom->wl_data_preparer(sel, &ddata, ev, &tmp_info); - if (success) - { - Dropable *dropable; - Eina_List *l; - - EINA_LIST_FOREACH(drops, l, dropable) - { - if (dropable->obj == sel->requestwidget) break; - dropable = NULL; - } - if (dropable) - { - cnp_debug("call dropcb\n"); - Dropable_Cbs *cbs; - Eina_Inlist *itr; - ddata.x = savedtypes.x; - ddata.y = savedtypes.y; - EINA_INLIST_FOREACH_SAFE(dropable->cbs_list, itr, cbs) - if ((cbs->types & dropable->last.format) && - cbs->dropcb) - cbs->dropcb(cbs->dropdata, dropable->obj, &ddata); - } - } - win = _wl_elm_widget_window_get(sel->requestwidget); - ecore_wl2_dnd_drag_end(_wl_default_seat_get(win, NULL)); - if (tmp_info) _tmpinfo_free(tmp_info); - free(ddata.data); - return; - } - } - - win = _wl_elm_widget_window_get(sel->requestwidget); - ecore_wl2_dnd_drag_end(_wl_default_seat_get(win, NULL)); - savedtypes.textreq = 0; -} - -static Dropable * -_wl_dropable_find(unsigned int win) -{ - Eina_List *l; - Dropable *dropable; - Ecore_Wl2_Window *window; - - if (!drops) return NULL; - - window = ecore_wl2_display_window_find(_elm_wl_display, win); - if (!window) return NULL; - - EINA_LIST_FOREACH(drops, l, dropable) - if (_wl_elm_widget_window_get(dropable->obj) == window) - return dropable; - - return NULL; -} - -static Evas * -_wl_evas_get_from_win(unsigned int win) -{ - Dropable *dropable = _wl_dropable_find(win); - return dropable ? evas_object_evas_get(dropable->obj) : NULL; -} - -static void -_wl_dropable_handle(Dropable *drop, Evas_Coord x, Evas_Coord y) -{ - Dropable *d, *last_dropable = NULL; - Dropable_Cbs *cbs; - Eina_Inlist *itr; - Eina_List *l; - - EINA_LIST_FOREACH(drops, l, d) - { - if (d->last.in) - { - last_dropable = d; - break; - } - } - - /* If we are on the same object, just update the position */ - if ((drop) && (last_dropable == drop)) - { - EINA_INLIST_FOREACH_SAFE(drop->cbs_list, itr, cbs) - if (cbs->poscb) - cbs->poscb(cbs->posdata, drop->obj, x, y, dragaction); - return; - } - /* We leave the last dropable */ - if (last_dropable) - { - EINA_INLIST_FOREACH_SAFE(last_dropable->cbs_list, itr, cbs) - if (cbs->leavecb) - cbs->leavecb(cbs->leavedata, last_dropable->obj); - last_dropable->last.in = EINA_FALSE; - } - /* We enter the new dropable */ - if (drop) - { - EINA_INLIST_FOREACH_SAFE(drop->cbs_list, itr, cbs) - if (cbs->entercb) - cbs->entercb(cbs->enterdata, drop->obj); - EINA_INLIST_FOREACH_SAFE(drop->cbs_list, itr, cbs) - if (cbs->poscb) - cbs->poscb(cbs->posdata, drop->obj, x, y, dragaction); - drop->last.in = EINA_TRUE; - } -} - -static void -_wl_dropable_all_clean(unsigned int win) -{ - Eina_List *l; - Dropable *dropable; - Ecore_Wl2_Window *window; - - window = ecore_wl2_display_window_find(_elm_wl_display, win); - if (!window) return; - - EINA_LIST_FOREACH(drops, l, dropable) - { - if (_wl_elm_widget_window_get(dropable->obj) == window) - { - dropable->last.x = 0; - dropable->last.y = 0; - dropable->last.in = EINA_FALSE; - } - } -} - -static Eina_Bool -_wl_drops_accept(const char *type) -{ - Eina_List *l; - Dropable *drop; - Eina_Bool will_accept = EINA_FALSE; - - if (!type) return EINA_FALSE; - - EINA_LIST_FOREACH(drops, l, drop) - { - Dropable_Cbs *cbs; - EINA_INLIST_FOREACH(drop->cbs_list, cbs) - { - for (int i = 0; convertion[i].translates ; ++i) - { - if (!(convertion[i].format & cbs->types)) continue; - - for (int j = 0; convertion[i].translates[j]; ++j) - { - if (!strncmp(type, convertion[i].translates[j], strlen(convertion[i].translates[j]))) - { - wl_cnp_selection.requestwidget = drop->obj; - return EINA_TRUE; - } - } - } - } - } - - return will_accept; -} - -static Ecore_Wl2_Window * -_wl_elm_widget_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; -} - -#endif - -#ifdef HAVE_ELEMENTARY_COCOA - -typedef struct _Cocoa_Cnp_Selection Cocoa_Cnp_Selection; - -struct _Cocoa_Cnp_Selection -{ - Ecore_Cocoa_Window *win; - Evas_Object *widget; - char *selbuf; - int buflen; - Evas_Object *requestwidget; - void *udata; - Elm_Sel_Format requestformat; - Elm_Drop_Cb datacb; - - Elm_Selection_Loss_Cb loss_cb; - void *loss_data; - int pb_count; - - Elm_Sel_Format format; - - Eina_Bool active : 1; -}; - -static Cocoa_Cnp_Selection _cocoa_cnp_sel; - -static Ecore_Cocoa_Window * -_cocoa_elm_widget_cocoa_window_get(const Evas_Object *obj) -{ - Evas_Object *top, *par; - Ecore_Cocoa_Window *win = NULL; - - if (elm_widget_is(obj)) - { - top = elm_widget_top_get(obj); - if (!top) - { - par = elm_widget_parent_widget_get(obj); - if (par) top = elm_widget_top_get(par); - } - if ((top) && (efl_isa(top, EFL_UI_WIN_CLASS))) - win = elm_win_cocoa_window_get(top); - } - if (!win) - { - // FIXME - CRI("WIN has not been retrieved!!!"); - } - - return win; -} - -static Ecore_Cocoa_Cnp_Type -_elm_sel_format_to_ecore_cocoa_cnp_type(Elm_Sel_Format fmt) -{ - Ecore_Cocoa_Cnp_Type type = 0; - - if ((fmt & ELM_SEL_FORMAT_TEXT) || - (fmt & ELM_SEL_FORMAT_VCARD)) - type |= ECORE_COCOA_CNP_TYPE_STRING; - if (fmt & ELM_SEL_FORMAT_MARKUP) - type |= ECORE_COCOA_CNP_TYPE_MARKUP; - if (fmt & ELM_SEL_FORMAT_HTML) - type |= ECORE_COCOA_CNP_TYPE_HTML; - if (fmt & ELM_SEL_FORMAT_IMAGE) - type |= ECORE_COCOA_CNP_TYPE_IMAGE; - - return type; -} - -static void -_cocoa_sel_obj_del_req_cb(void *data, - Evas *e EINA_UNUSED, - Evas_Object *obj, - void *ev_info EINA_UNUSED) -{ - Cocoa_Cnp_Selection *sel = data; - if (sel->requestwidget == obj) sel->requestwidget = NULL; -} - -static void -_cocoa_sel_obj_del_cb(void *data, - Evas *e EINA_UNUSED, - Evas_Object *obj, - void *ev_info EINA_UNUSED) -{ - Cocoa_Cnp_Selection *sel = data; - if (sel->widget == obj) - { - sel->widget = NULL; - sel->loss_cb = NULL; - sel->loss_data = NULL; - } - if (dragwidget == obj) dragwidget = NULL; -} - -static void -_job_pb_cb(void *data) -{ - Cocoa_Cnp_Selection *sel = data; - Elm_Selection_Data ddata; - Ecore_Cocoa_Cnp_Type type, get_type; - void *pbdata; - int pbdata_len; - - if (sel->datacb) - { - ddata.x = 0; - ddata.y = 0; - - /* Pass to cocoa clipboard */ - type = _elm_sel_format_to_ecore_cocoa_cnp_type(sel->requestformat); - pbdata = ecore_cocoa_clipboard_get(&pbdata_len, type, &get_type); - - ddata.format = ELM_SEL_FORMAT_NONE; - if (get_type & ECORE_COCOA_CNP_TYPE_STRING) - ddata.format |= ELM_SEL_FORMAT_TEXT; - if (get_type & ECORE_COCOA_CNP_TYPE_MARKUP) - ddata.format |= ELM_SEL_FORMAT_MARKUP; - if (get_type & ECORE_COCOA_CNP_TYPE_IMAGE) - ddata.format |= ELM_SEL_FORMAT_IMAGE; - if (get_type & ECORE_COCOA_CNP_TYPE_HTML) - ddata.format |= ELM_SEL_FORMAT_HTML; - - ddata.data = pbdata; - ddata.len = pbdata_len; - ddata.action = ELM_XDND_ACTION_UNKNOWN; - sel->datacb(sel->udata, sel->requestwidget, &ddata); - free(pbdata); - } -} - -static Eina_Bool -_cocoa_elm_cnp_selection_set(Ecore_Cocoa_Window *win, - Evas_Object *obj, - Elm_Sel_Type selection, - Elm_Sel_Format format, - const void *selbuf, - size_t buflen) -{ - Cocoa_Cnp_Selection *sel = &_cocoa_cnp_sel; - Ecore_Cocoa_Cnp_Type type; - Eina_Bool ok = EINA_TRUE; - - if ((!selbuf) && (format != ELM_SEL_FORMAT_IMAGE)) - return elm_object_cnp_selection_clear(obj, selection); - if (buflen <= 0) return EINA_FALSE; - - if (sel->loss_cb) sel->loss_cb(sel->loss_data, selection); - if (sel->widget) - evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL, - _cocoa_sel_obj_del_cb, sel); - - sel->widget = obj; - sel->win = win; - sel->format = format; - sel->loss_cb = NULL; - sel->loss_data = NULL; - - evas_object_event_callback_add(sel->widget, EVAS_CALLBACK_DEL, - _cocoa_sel_obj_del_cb, sel); - ELM_SAFE_FREE(sel->selbuf, free); - sel->buflen = 0; - if (selbuf) - { - sel->selbuf = malloc(buflen + 1); - if (EINA_UNLIKELY(!sel->selbuf)) - { - CRI("Failed to allocate memory!"); - elm_object_cnp_selection_clear(obj, selection); - return EINA_FALSE; - } - memcpy(sel->selbuf, selbuf, buflen); - sel->selbuf[buflen] = 0; - sel->buflen = buflen; - type = _elm_sel_format_to_ecore_cocoa_cnp_type(format); - ecore_cocoa_clipboard_set(selbuf, buflen, type); - } - - return ok; -} - -static void -_cocoa_elm_cnp_selection_loss_callback_set(Evas_Object *obj EINA_UNUSED, - Elm_Sel_Type selection EINA_UNUSED, - Elm_Selection_Loss_Cb func EINA_UNUSED, - const void *data EINA_UNUSED) -{ - // Currently, we have no way to track changes in Cocoa pasteboard. - // Therefore, don't track this... - //sel->loss_cb = func; - //sel->loss_data = (void *)data; -} - -static Eina_Bool -_cocoa_elm_cnp_selection_clear(Evas_Object *obj EINA_UNUSED, - Elm_Sel_Type selection EINA_UNUSED) -{ - Cocoa_Cnp_Selection *sel = &_cocoa_cnp_sel; - - if (sel->widget) - evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL, - _cocoa_sel_obj_del_cb, sel); - if (sel->requestwidget) - evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL, - _cocoa_sel_obj_del_req_cb, sel); - - sel->widget = NULL; - sel->requestwidget = NULL; - sel->loss_cb = NULL; - sel->loss_data = NULL; - ELM_SAFE_FREE(sel->selbuf, free); - sel->buflen = 0; - ecore_cocoa_clipboard_clear(); - - return EINA_TRUE; -} - -static Eina_Bool -_cocoa_elm_cnp_selection_get(const Evas_Object *obj, - Ecore_Cocoa_Window *win, - Elm_Sel_Type selection EINA_UNUSED, - Elm_Sel_Format format, - Elm_Drop_Cb datacb, - void *udata) -{ - Cocoa_Cnp_Selection *sel = &_cocoa_cnp_sel; - - if (sel->requestwidget) - evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL, - _cocoa_sel_obj_del_req_cb, sel); - - sel->requestformat = format; - sel->requestwidget = (Evas_Object *)obj; - sel->win = win; - sel->datacb = datacb; - sel->udata = udata; - - ecore_job_add(_job_pb_cb, sel); - - evas_object_event_callback_add(sel->requestwidget, EVAS_CALLBACK_DEL, - _cocoa_sel_obj_del_req_cb, sel); - - return EINA_TRUE; -} - - -#endif - -//////////////////////////////////////////////////////////////////////////// -// for local (Within 1 app/process) cnp (used by fb as fallback -//////////////////////////////////////////////////////////////////////////// -#if 1 -typedef struct _Local_Selinfo Local_Selinfo; - -struct _Local_Selinfo -{ - Elm_Sel_Format format; - struct { - char *buf; - size_t size; - } sel; - struct { - Evas_Object *obj; - Elm_Drop_Cb func; - void *data; - Ecore_Job *job; - } get; -}; - -// for ELM_SEL_TYPE_PRIMARY, ELM_SEL_TYPE_SECONDARY, ELM_SEL_TYPE_XDND, -// ELM_SEL_TYPE_CLIPBOARD -static Local_Selinfo _local_selinfo[4]; - -static void _local_get_job(void *data); - -static Eina_Bool _local_elm_cnp_init(void); -static Eina_Bool _local_elm_cnp_selection_set(Evas_Object *obj EINA_UNUSED, Elm_Sel_Type selection, Elm_Sel_Format format, const void *selbuf, size_t buflen); -static void _local_elm_cnp_selection_loss_callback_set(Evas_Object *obj EINA_UNUSED, Elm_Sel_Type selection EINA_UNUSED, Elm_Selection_Loss_Cb func EINA_UNUSED, const void *data EINA_UNUSED); -static Eina_Bool _local_elm_object_cnp_selection_clear(Evas_Object *obj EINA_UNUSED, Elm_Sel_Type selection); -static Eina_Bool _local_elm_cnp_selection_get(const Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format EINA_UNUSED, Elm_Drop_Cb datacb, void *udata); -static Eina_Bool _local_elm_drop_target_add(Evas_Object *obj EINA_UNUSED, Elm_Sel_Format format EINA_UNUSED, - Elm_Drag_State entercb EINA_UNUSED, void *enterdata EINA_UNUSED, - Elm_Drag_State leavecb EINA_UNUSED, void *leavedata EINA_UNUSED, - Elm_Drag_Pos poscb EINA_UNUSED, void *posdata EINA_UNUSED, - Elm_Drop_Cb dropcb EINA_UNUSED, void *dropdata EINA_UNUSED); -static Eina_Bool _local_elm_drag_start(Evas_Object *obj EINA_UNUSED, - Elm_Sel_Format format EINA_UNUSED, - const char *data EINA_UNUSED, - Elm_Xdnd_Action action EINA_UNUSED, - Elm_Drag_Icon_Create_Cb createicon EINA_UNUSED, - void *createdata EINA_UNUSED, - Elm_Drag_Pos dragpos EINA_UNUSED, - void *dragdata EINA_UNUSED, - Elm_Drag_Accept acceptcb EINA_UNUSED, - void *acceptdata EINA_UNUSED, - Elm_Drag_State dragdone EINA_UNUSED, - void *donecbdata EINA_UNUSED); -static Eina_Bool _local_elm_selection_selection_has_owner(Evas_Object *obj EINA_UNUSED); - -static void -_local_get_job(void *data) -{ - Local_Selinfo *info = data; - Elm_Selection_Data ev; - - info->get.job = NULL; - ev.x = 0; - ev.y = 0; - ev.format = info->format; - ev.data = info->sel.buf; - ev.len = info->sel.size; - ev.action = ELM_XDND_ACTION_UNKNOWN; - if (info->get.func) - info->get.func(info->get.data, info->get.obj, &ev); -} - -static Eina_Bool -_local_elm_cnp_init(void) -{ - static int _init_count = 0; - - if (_init_count > 0) return EINA_TRUE; - _init_count++; - memset(&(_local_selinfo), 0, sizeof(_local_selinfo)); - return EINA_TRUE; -} - -static Eina_Bool -_local_elm_cnp_selection_set(Evas_Object *obj EINA_UNUSED, - Elm_Sel_Type selection, Elm_Sel_Format format, - const void *selbuf, size_t buflen) -{ - _local_elm_cnp_init(); - free(_local_selinfo[selection].sel.buf); - _local_selinfo[selection].format = format; - _local_selinfo[selection].sel.buf = malloc(buflen + 1); - if ((_local_selinfo[selection].sel.buf) && (selbuf)) - { - memcpy(_local_selinfo[selection].sel.buf, selbuf, buflen); - _local_selinfo[selection].sel.buf[buflen] = 0; - _local_selinfo[selection].sel.size = buflen; - } - else - _local_selinfo[selection].sel.size = 0; - return EINA_TRUE; -} - -static void -_local_elm_cnp_selection_loss_callback_set(Evas_Object *obj EINA_UNUSED, - Elm_Sel_Type selection EINA_UNUSED, - Elm_Selection_Loss_Cb func EINA_UNUSED, - const void *data EINA_UNUSED) -{ - _local_elm_cnp_init(); - // this doesn't need to do anything as we never lose selection to anyone - // as thisis local -} - -static Eina_Bool -_local_elm_object_cnp_selection_clear(Evas_Object *obj EINA_UNUSED, - Elm_Sel_Type selection) -{ - _local_elm_cnp_init(); - ELM_SAFE_FREE(_local_selinfo[selection].sel.buf, free); - _local_selinfo[selection].sel.size = 0; - return EINA_TRUE; -} - -static Eina_Bool -_local_elm_cnp_selection_get(const Evas_Object *obj, - Elm_Sel_Type selection, - Elm_Sel_Format format EINA_UNUSED, - Elm_Drop_Cb datacb, void *udata) -{ - _local_elm_cnp_init(); - if (_local_selinfo[selection].get.job) - ecore_job_del(_local_selinfo[selection].get.job); - _local_selinfo[selection].get.obj = (Evas_Object *)obj; - _local_selinfo[selection].get.func = datacb; - _local_selinfo[selection].get.data = udata; - _local_selinfo[selection].get.job = - ecore_job_add(_local_get_job, &(_local_selinfo[selection])); - return EINA_TRUE; -} - -static Eina_Bool -_local_elm_drop_target_add(Evas_Object *obj EINA_UNUSED, - Elm_Sel_Format format EINA_UNUSED, - Elm_Drag_State entercb EINA_UNUSED, - void *enterdata EINA_UNUSED, - Elm_Drag_State leavecb EINA_UNUSED, - void *leavedata EINA_UNUSED, - Elm_Drag_Pos poscb EINA_UNUSED, - void *posdata EINA_UNUSED, - Elm_Drop_Cb dropcb EINA_UNUSED, - void *dropdata EINA_UNUSED) -{ - // XXX: implement me - _local_elm_cnp_init(); - return EINA_FALSE; -} - -static Eina_Bool -_local_elm_drop_target_del(Evas_Object *obj, Elm_Sel_Format format, - Elm_Drag_State entercb, void *enterdata, - Elm_Drag_State leavecb, void *leavedata, - Elm_Drag_Pos poscb, void *posdata, - Elm_Drop_Cb dropcb, void *dropdata) -{ - Dropable *dropable = NULL; - - _local_elm_cnp_init(); - - dropable = efl_key_data_get(obj, "__elm_dropable"); - if (dropable) - { - Eina_Inlist *itr; - Dropable_Cbs *cbs_info; - /* Look for the callback in the list */ - EINA_INLIST_FOREACH_SAFE(dropable->cbs_list, itr, cbs_info) - if (cbs_info->entercb == entercb && cbs_info->enterdata == enterdata && - cbs_info->leavecb == leavecb && cbs_info->leavedata == leavedata && - cbs_info->poscb == poscb && cbs_info->posdata == posdata && - cbs_info->dropcb == dropcb && cbs_info->dropdata == dropdata && - cbs_info->types == format) - { - dropable->cbs_list = eina_inlist_remove(dropable->cbs_list, - EINA_INLIST_GET(cbs_info)); - free(cbs_info); - } - /* In case no more callbacks are listed for the object */ - if (!dropable->cbs_list) - { - drops = eina_list_remove(drops, dropable); - efl_key_data_set(obj, "__elm_dropable", NULL); - free(dropable); - dropable = NULL; - evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, - _all_drop_targets_cbs_del); - } - if (!drops) - { - _elm_cnp_shutdown(); - } - return EINA_TRUE; - } - - return EINA_FALSE; -} - -static Eina_Bool -_local_elm_drag_start(Evas_Object *obj EINA_UNUSED, - Elm_Sel_Format format EINA_UNUSED, - const char *data EINA_UNUSED, - Elm_Xdnd_Action action EINA_UNUSED, - Elm_Drag_Icon_Create_Cb createicon EINA_UNUSED, - void *createdata EINA_UNUSED, - Elm_Drag_Pos dragpos EINA_UNUSED, - void *dragdata EINA_UNUSED, - Elm_Drag_Accept acceptcb EINA_UNUSED, - void *acceptdata EINA_UNUSED, - Elm_Drag_State dragdone EINA_UNUSED, - void *donecbdata EINA_UNUSED) -{ - // XXX: implement me - _local_elm_cnp_init(); - return EINA_FALSE; -} - -static Eina_Bool -_local_elm_drag_action_set(Evas_Object *obj EINA_UNUSED, - Elm_Xdnd_Action action EINA_UNUSED) -{ - // XXX: implement me - _local_elm_cnp_init(); - return EINA_FALSE; -} - -static Eina_Bool -_local_elm_selection_selection_has_owner(Evas_Object *obj EINA_UNUSED) -{ - _local_elm_cnp_init(); - if (_local_selinfo[ELM_SEL_TYPE_CLIPBOARD].sel.buf) return EINA_TRUE; - return EINA_FALSE; -} -#endif - -// win32 specific stuff -//////////////////////////////////////////////////////////////////////////// -#ifdef HAVE_ELEMENTARY_WIN32 - -typedef struct _Win32_Cnp_Selection Win32_Cnp_Selection; - -struct _Win32_Cnp_Selection -{ - const char *debug; - Evas_Object *widget; - char *selbuf; - Evas_Object *requestwidget; - void *udata; - Elm_Sel_Format requestformat; - Elm_Drop_Cb datacb; - Eina_Bool (*set)(const Ecore_Win32_Window *window, const void *data, int size); - Eina_Bool (*clear)(const Ecore_Win32_Window *window); - Eina_Bool (*get)(const Ecore_Win32_Window *window , void **data, int *size); - Elm_Selection_Loss_Cb loss_cb; - void *loss_data; - - Elm_Sel_Format format; - Ecore_Win32_Selection ecore_sel; - Ecore_Win32_Window *win; - Elm_Xdnd_Action action; - - Eina_Bool active : 1; -}; - -#define ARRAYINIT(foo) [foo] = - -static Win32_Cnp_Selection _win32_selections[ELM_SEL_TYPE_CLIPBOARD + 1] = -{ - ARRAYINIT(ELM_SEL_TYPE_PRIMARY) - { - .debug = "Primary", - .ecore_sel = ECORE_WIN32_SELECTION_PRIMARY, - .set = ecore_win32_clipboard_set, - .clear = ecore_win32_clipboard_clear, - .get = ecore_win32_clipboard_get, - }, - ARRAYINIT(ELM_SEL_TYPE_SECONDARY) - { - .debug = "Secondary", - .ecore_sel = ECORE_WIN32_SELECTION_OTHER, - }, - ARRAYINIT(ELM_SEL_TYPE_XDND) - { - .debug = "XDnD", - .ecore_sel = ECORE_WIN32_SELECTION_OTHER, - }, - ARRAYINIT(ELM_SEL_TYPE_CLIPBOARD) - { - .debug = "Clipboard", - .ecore_sel = ECORE_WIN32_SELECTION_CLIPBOARD, - .set = ecore_win32_clipboard_set, - .clear = ecore_win32_clipboard_clear, - .get = ecore_win32_clipboard_get, - } -}; - -static char * -_win32_text_n_to_rn(char *intext) -{ - size_t size = 0, newlines = 0; - char *outtext = NULL, *p, *o; - - if (!intext) return NULL; - for (p = intext; *p; p++) - { - if (*p == '\n') newlines++; - size++; - } - outtext = malloc(size + newlines + 1); - if (!outtext) return intext; - for (p = intext, o = outtext; *p; p++, o++) - { - if (*p == '\n') - { - o++; - *p = '\r'; - } - *o = *p; - } - *o = '\0'; - free(intext); - return outtext; -} - -static char * -_win32_text_rn_to_n(char *intext) -{ - char *outtext = NULL, *p, *o; - - if (!intext) return NULL; - outtext = malloc(strlen(intext) + 1); - if (!outtext) return intext; - for (p = intext, o = outtext; *p; p++, o++) - { - if ((*p == '\r') && (p[1] == '\n')) - { - p++; - *p = '\n'; - } - else *o = *p; - } - *o = '\0'; - free(intext); - return outtext; -} - -static void -_win32_sel_obj_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) -{ - Win32_Cnp_Selection *sel = data; - if (sel->widget == obj) sel->widget = NULL; - if (dragwidget == obj) dragwidget = NULL; -} - -static void -_win32_sel_obj_del2(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) -{ - Win32_Cnp_Selection *sel = data; - if (sel->requestwidget == obj) sel->requestwidget = NULL; -} - -static Eina_Bool -_win32_elm_cnp_init(void) -{ - static int _init_count = 0; - - if (_init_count > 0) return EINA_TRUE; - _init_count++; - return EINA_TRUE; -} - -static Ecore_Win32_Window * -_win32_elm_widget_window_get(const Evas_Object *obj) -{ - Evas_Object *top; - Ecore_Win32_Window *win = NULL; - - if (elm_widget_is(obj)) - { - top = elm_widget_top_get(obj); - if (!top) - { - Evas_Object *par; - par = elm_widget_parent_widget_get(obj); - if (par) top = elm_widget_top_get(par); - } - if (top && (efl_isa(top, EFL_UI_WIN_CLASS))) - win = elm_win_win32_window_get(top); - } - - if (!win) - { - Ecore_Evas *ee; - Evas *evas; - const char *engine_name; - - evas = evas_object_evas_get(obj); - if (!evas) return NULL; - - ee = ecore_evas_ecore_evas_get(evas); - if (!ee) 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; - win = ecore_evas_win32_window_get(ee); - } - else - { - if ((strcmp(engine_name, ELM_SOFTWARE_WIN32) == 0) || - (strcmp(engine_name, ELM_SOFTWARE_DDRAW) == 0)) - return ecore_evas_win32_window_get(ee); - } - } - - return win; -} - -static Eina_Bool -_win32_elm_cnp_selection_set(Ecore_Win32_Window *win, Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, const void *selbuf, size_t buflen) -{ - Win32_Cnp_Selection *sel; - - if (selection != ELM_SEL_TYPE_CLIPBOARD) - return EINA_FALSE; - - _win32_elm_cnp_init(); - if ((!selbuf) && (format != ELM_SEL_FORMAT_IMAGE)) - return elm_object_cnp_selection_clear(obj, selection); - - sel = _win32_selections + selection; - if (sel->widget != obj && sel->loss_cb) sel->loss_cb(sel->loss_data, selection); - if (sel->widget) - evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL, - _win32_sel_obj_del, sel); - sel->active = EINA_TRUE; - sel->widget = obj; - sel->win = win; - if (sel->set) sel->set(win, selbuf, buflen); - sel->format = format; - sel->loss_cb = NULL; - sel->loss_data = NULL; - - evas_object_event_callback_add - (sel->widget, EVAS_CALLBACK_DEL, _win32_sel_obj_del, sel); - - ELM_SAFE_FREE(sel->selbuf, free); - if (selbuf) - { - if (format == ELM_SEL_FORMAT_IMAGE) - { - // selbuf is actual image data, not text/string - sel->selbuf = malloc(buflen + 1); - if (!sel->selbuf) - { - elm_object_cnp_selection_clear(obj, selection); - return EINA_FALSE; - } - memcpy(sel->selbuf, selbuf, buflen); - sel->selbuf[buflen] = 0; - } - else - sel->selbuf = strdup((char*)selbuf); - } - - return EINA_TRUE; -} - -static void -_win32_elm_cnp_selection_loss_callback_set(Evas_Object *obj EINA_UNUSED, Elm_Sel_Type selection, Elm_Selection_Loss_Cb func, const void *data) -{ - Win32_Cnp_Selection *sel; - - if (selection != ELM_SEL_TYPE_CLIPBOARD) - return; - - _win32_elm_cnp_init(); - sel = _win32_selections + selection; - sel->loss_cb = func; - sel->loss_data = (void *)data; -} - -static Eina_Bool -_win32_elm_object_cnp_selection_clear(Ecore_Win32_Window *win, Evas_Object *obj, Elm_Sel_Type selection) -{ - Win32_Cnp_Selection *sel; - - if (selection != ELM_SEL_TYPE_CLIPBOARD) - return EINA_FALSE; - - _win32_elm_cnp_init(); - - sel = _win32_selections + selection; - - /* No longer this selection: Consider it gone! */ - if ((!sel->active) || (sel->widget != obj)) - return EINA_TRUE; - - if (sel->widget) - evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL, - _win32_sel_obj_del, sel); - if (sel->requestwidget) - evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL, - _win32_sel_obj_del2, sel); - sel->widget = NULL; - sel->requestwidget = NULL; - sel->loss_cb = NULL; - sel->loss_data = NULL; - - sel->active = EINA_FALSE; - ELM_SAFE_FREE(sel->selbuf, free); - /* sel->clear(win); */ - - return EINA_TRUE; -} - -static Eina_Bool -_win32_elm_cnp_selection_get(Ecore_Win32_Window *win, - const Evas_Object *obj, - Elm_Sel_Type selection, - Elm_Sel_Format format, - Elm_Drop_Cb datacb, - void *udata) -{ - Win32_Cnp_Selection *sel; - void *data; - int size; - - if (selection != ELM_SEL_TYPE_CLIPBOARD) - return EINA_FALSE; - - _win32_elm_cnp_init(); - - sel = _win32_selections + selection; - - if (sel->requestwidget) - evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL, - _win32_sel_obj_del2, sel); - sel->requestformat = format; - sel->requestwidget = (Evas_Object *)obj; - sel->win = win; - sel->get(win, &data, &size); - sel->datacb = datacb; - sel->udata = udata; - - if (!data || (size <= 0)) - goto cb_add; - - if ((sel->format & ELM_SEL_FORMAT_MARKUP) || - (sel->format & ELM_SEL_FORMAT_HTML)) - { - char *str; - - str = (char *)malloc(size + 1); - if (str) - { - memcpy(str, data, size); - str[size] = '\0'; - data = _win32_text_n_to_rn(_elm_util_mkup_to_text(str)); - free(str); - if (data) - size = strlen(data); - else - size = 0; - } - else - { - free(data); - data = NULL; - } - } - - if (sel->datacb && data && (size > 0)) - { - Elm_Selection_Data sdata; - - sdata.x = sdata.y = 0; - sdata.format = ELM_SEL_FORMAT_TEXT; - sdata.data = data; - sdata.len = size; - sdata.action = sel->action; - sel->datacb(sel->udata, sel->requestwidget, &sdata); - } - - if (data) - free(data); - - cb_add: - evas_object_event_callback_add - (sel->requestwidget, EVAS_CALLBACK_DEL, _win32_sel_obj_del2, sel); - - return EINA_TRUE; -} - -#endif /* HAVE_ELEMENTARY_WIN32 */ - -// common internal funcs -//////////////////////////////////////////////////////////////////////////// -static Eina_Bool -_elm_cnp_init(void) -{ - int i; - if (_elm_cnp_init_count > 0) return EINA_TRUE; - _elm_cnp_init_count++; - ELM_CNP_EVENT_SELECTION_CHANGED = ecore_event_type_new(); - text_uri = eina_stringshare_add("text/uri-list"); - _types_hash = eina_hash_string_small_new(NULL); - for (i = 0; i < CNP_N_ATOMS; i++) - { - eina_hash_add(_types_hash, _atoms[i].name, &_atoms[i]); - } - return EINA_TRUE; -} - -static Eina_Bool -_elm_cnp_shutdown(void) -{ - if (!_elm_cnp_init_count) return EINA_TRUE; - if (--_elm_cnp_init_count > 0) return EINA_TRUE; - ELM_CNP_EVENT_SELECTION_CHANGED = -1; - eina_stringshare_del(text_uri); - text_uri = NULL; - ELM_SAFE_FREE(_types_hash, eina_hash_free); - return EINA_TRUE; -} - -/* 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. */ -static Tmp_Info * -_tempfile_new(int size) -{ -#ifdef HAVE_MMAN_H - Tmp_Info *info; - const char *tmppath = NULL; - mode_t cur_umask; - int len; - - info = calloc(1, sizeof(Tmp_Info)); - if (!info) return NULL; -#if defined(HAVE_GETUID) && defined(HAVE_GETEUID) - if (getuid() == geteuid()) -#endif - tmppath = getenv("TMP"); - if (!tmppath) tmppath = P_tmpdir; - len = snprintf(NULL, 0, "%s/%sXXXXXX", tmppath, "elmcnpitem-"); - if (len < 0) goto on_error; - len++; - info->filename = malloc(len); - if (!info->filename) goto on_error; - snprintf(info->filename,len,"%s/%sXXXXXX", tmppath, "elmcnpitem-"); - cur_umask = umask(S_IRWXO | S_IRWXG); - info->fd = mkstemp(info->filename); - umask(cur_umask); - if (info->fd < 0) goto on_error; -# ifdef __linux__ - { - char *tmp; - /* And before someone says anything see POSIX 1003.1-2008 page 400 */ - long pid; - - pid = (long)getpid(); - /* Use pid instead of /proc/self: That way if can be passed around */ - len = snprintf(NULL,0,"/proc/%li/fd/%i", pid, info->fd); - len++; - tmp = malloc(len); - if (tmp) - { - snprintf(tmp,len, "/proc/%li/fd/%i", pid, info->fd); - unlink(info->filename); - free(info->filename); - info->filename = tmp; - } - } -# endif - cnp_debug("filename is %s\n", info->filename); - if (size < 1) goto on_error; - /* Map it in */ - if (ftruncate(info->fd, size)) - { - perror("ftruncate"); - goto on_error; - } - eina_mmap_safety_enabled_set(EINA_TRUE); - info->map = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, info->fd, 0); - if (info->map == MAP_FAILED) - { - perror("mmap"); - goto on_error; - } - return info; - - on_error: - if (info->fd >= 0) close(info->fd); - info->fd = -1; - /* Set map to NULL and return */ - info->map = NULL; - info->len = 0; - free(info->filename); - free(info); - return NULL; -#else - (void) size; - return NULL; -#endif -} - -static int -_tmpinfo_free(Tmp_Info *info) -{ - if (!info) return 0; - free(info->filename); - free(info); - return 0; -} - -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -// common exposed funcs -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -EAPI Eina_Bool -elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection, - Elm_Sel_Format format, const void *selbuf, size_t buflen) -{ - if (selection > ELM_SEL_TYPE_CLIPBOARD) return EINA_FALSE; - if (!_elm_cnp_init_count) _elm_cnp_init(); -#ifdef HAVE_ELEMENTARY_X - Ecore_X_Window xwin = _x11_elm_widget_xwin_get(obj); - if (xwin) - return _x11_elm_cnp_selection_set(xwin, obj, selection, format, selbuf, buflen); -#endif -#ifdef HAVE_ELEMENTARY_WL2 - if (_wl_elm_widget_window_get(obj)) - return _wl_elm_cnp_selection_set(obj, selection, format, selbuf, buflen); -#endif -#ifdef HAVE_ELEMENTARY_COCOA - Ecore_Cocoa_Window *win = _cocoa_elm_widget_cocoa_window_get(obj); - if (win) - return _cocoa_elm_cnp_selection_set(win, obj, selection, format, selbuf, buflen); -#endif -#ifdef HAVE_ELEMENTARY_WIN32 - Ecore_Win32_Window *win; - - win = _win32_elm_widget_window_get(obj); - if (win) - return _win32_elm_cnp_selection_set(win, obj, selection, format, selbuf, buflen); -#endif - return _local_elm_cnp_selection_set(obj, selection, format, selbuf, buflen); -} - -EAPI void -elm_cnp_selection_loss_callback_set(Evas_Object *obj, Elm_Sel_Type selection, - Elm_Selection_Loss_Cb func, - const void *data) -{ - if (selection > ELM_SEL_TYPE_CLIPBOARD) return; - if (!_elm_cnp_init_count) _elm_cnp_init(); -#ifdef HAVE_ELEMENTARY_X - if (_x11_elm_widget_xwin_get(obj)) - _x11_elm_cnp_selection_loss_callback_set(obj, selection, func, data); -#endif -#ifdef HAVE_ELEMENTARY_WL2 - if (_wl_elm_widget_window_get(obj)) - _wl_elm_cnp_selection_loss_callback_set(obj, selection, func, data); -#endif -#ifdef HAVE_ELEMENTARY_COCOA - if (_cocoa_elm_widget_cocoa_window_get(obj)) - _cocoa_elm_cnp_selection_loss_callback_set(obj, selection, func, data); -#endif -#ifdef HAVE_ELEMENTARY_WIN32 - if (_win32_elm_widget_window_get(obj)) - _win32_elm_cnp_selection_loss_callback_set(obj, selection, func, data); -#endif - _local_elm_cnp_selection_loss_callback_set(obj, selection, func, data); -} - -EAPI Eina_Bool -elm_object_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type selection) -{ - if (selection > ELM_SEL_TYPE_CLIPBOARD) return EINA_FALSE; - if (!_elm_cnp_init_count) _elm_cnp_init(); -#ifdef HAVE_ELEMENTARY_X - if (_x11_elm_widget_xwin_get(obj)) - return _x11_elm_object_cnp_selection_clear(obj, selection); -#endif -#ifdef HAVE_ELEMENTARY_WL2 - if (_wl_elm_widget_window_get(obj)) - return _wl_elm_cnp_selection_clear(obj, selection); -#endif -#ifdef HAVE_ELEMENTARY_COCOA - if (_cocoa_elm_widget_cocoa_window_get(obj)) - return _cocoa_elm_cnp_selection_clear(obj, selection); -#endif -#ifdef HAVE_ELEMENTARY_WIN32 - Ecore_Win32_Window *win; - - win = _win32_elm_widget_window_get(obj); - if (win) - return _win32_elm_object_cnp_selection_clear(win, obj, selection); -#endif - return _local_elm_object_cnp_selection_clear(obj, selection); -} - -EAPI Eina_Bool -elm_cnp_selection_get(const Evas_Object *obj, Elm_Sel_Type selection, - Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata) -{ - if (selection > ELM_SEL_TYPE_CLIPBOARD) return EINA_FALSE; - if (!_elm_cnp_init_count) _elm_cnp_init(); -#ifdef HAVE_ELEMENTARY_X - Ecore_X_Window xwin = _x11_elm_widget_xwin_get(obj); - if (xwin) - return _x11_elm_cnp_selection_get(xwin, obj, selection, format, datacb, udata); -#endif -#ifdef HAVE_ELEMENTARY_WL2 - if (_wl_elm_widget_window_get(obj)) - return _wl_elm_cnp_selection_get(obj, selection, format, datacb, udata); -#endif -#ifdef HAVE_ELEMENTARY_COCOA - Ecore_Cocoa_Window *win = _cocoa_elm_widget_cocoa_window_get(obj); - if (win) - return _cocoa_elm_cnp_selection_get(obj, win, selection, format, datacb, udata); -#endif -#ifdef HAVE_ELEMENTARY_WIN32 - Ecore_Win32_Window *win; - - win = _win32_elm_widget_window_get(obj); - if (win) - return _win32_elm_cnp_selection_get(win, obj, selection, format, datacb, udata); -#endif - return _local_elm_cnp_selection_get(obj, selection, format, datacb, udata); -} - -//////////////////////////////////////////////////////////////////////////// - -/** - * Add a widget as drop target. - */ -EAPI Eina_Bool -elm_drop_target_add(Evas_Object *obj, Elm_Sel_Format format, - Elm_Drag_State entercb, void *enterdata, - Elm_Drag_State leavecb, void *leavedata, - Elm_Drag_Pos poscb, void *posdata, - Elm_Drop_Cb dropcb, void *dropdata) -{ - if (!_elm_cnp_init_count) _elm_cnp_init(); -#ifdef HAVE_ELEMENTARY_X - if (_x11_elm_widget_xwin_get(obj)) - return _x11_elm_drop_target_add(obj, format, entercb, enterdata, - leavecb, leavedata, poscb, posdata, - dropcb, dropdata); -#endif -#ifdef HAVE_ELEMENTARY_WL2 - if (_wl_elm_widget_window_get(obj)) - return _wl_elm_drop_target_add(obj, format, entercb, enterdata, - leavecb, leavedata, poscb, posdata, - dropcb, dropdata); -#endif - return _local_elm_drop_target_add(obj, format, entercb, enterdata, - leavecb, leavedata, poscb, posdata, - dropcb, dropdata); -} - -EAPI Eina_Bool -elm_drop_target_del(Evas_Object *obj, Elm_Sel_Format format, - Elm_Drag_State entercb, void *enterdata, - Elm_Drag_State leavecb, void *leavedata, - Elm_Drag_Pos poscb, void *posdata, - Elm_Drop_Cb dropcb, void *dropdata) -{ - if (!_elm_cnp_init_count) _elm_cnp_init(); -#ifdef HAVE_ELEMENTARY_X - if (_x11_elm_widget_xwin_get(obj)) - return _x11_elm_drop_target_del(obj, format, entercb, enterdata, - leavecb, leavedata, poscb, posdata, dropcb, dropdata); -#endif -#ifdef HAVE_ELEMENTARY_WL2 - if (_wl_elm_widget_window_get(obj)) - return _wl_elm_drop_target_del(obj, format, entercb, enterdata, - leavecb, leavedata, poscb, posdata, dropcb, dropdata); -#endif - /* FIXME: Not the best place for an error message, but meh. - * This code path is actually valid if running in framebuffer, but it still shouldn't - * be getting here because the drop target shouldn't be added. This is an error - * and it's because of some stupid handling in both the X11 and the wayland backends - * as seen in the commit that introduced this comment. - * Window check is probably not the best idea, you should be doing engine check instead. */ - ERR("Please contact developers, you should probably not get here."); - return _local_elm_drop_target_del(obj, format, entercb, enterdata, - leavecb, leavedata, poscb, posdata, dropcb, dropdata); -} - -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 createicon, void *createdata, - Elm_Drag_Pos dragpos, void *dragdata, - Elm_Drag_Accept acceptcb, void *acceptdata, - Elm_Drag_State dragdone, void *donecbdata) -{ - if (!_elm_cnp_init_count) _elm_cnp_init(); -#ifdef HAVE_ELEMENTARY_X - if (_x11_elm_widget_xwin_get(obj)) - return _x11_elm_drag_start(obj, format, data, action, - createicon, createdata, - dragpos, dragdata, - acceptcb, acceptdata, - dragdone, donecbdata); -#endif -#ifdef HAVE_ELEMENTARY_WL2 - if (_wl_elm_widget_window_get(obj)) - return _wl_elm_drag_start(obj, format, data, action, - createicon, createdata, - dragpos, dragdata, - acceptcb, acceptdata, - dragdone, donecbdata); -#endif - return _local_elm_drag_start(obj, format, data, action, - createicon, createdata, - dragpos, dragdata, - acceptcb, acceptdata, - dragdone, donecbdata); -} - -EAPI Eina_Bool -elm_drag_action_set(Evas_Object *obj, Elm_Xdnd_Action action) -{ - if (!_elm_cnp_init_count) _elm_cnp_init(); -#ifdef HAVE_ELEMENTARY_X - if (_x11_elm_widget_xwin_get(obj)) - return _x11_elm_drag_action_set(obj, action); -#endif -#ifdef HAVE_ELEMENTARY_WL2 - if (_wl_elm_widget_window_get(obj)) - return _wl_elm_drag_action_set(obj, action); -#endif - return _local_elm_drag_action_set(obj, action); -} - -EAPI Eina_Bool -elm_selection_selection_has_owner(Evas_Object *obj) -{ - if (!_elm_cnp_init_count) _elm_cnp_init(); -#ifdef HAVE_ELEMENTARY_X - if (_x11_elm_widget_xwin_get(obj)) - return _x11_elm_selection_selection_has_owner(obj); -#endif -#ifdef HAVE_ELEMENTARY_WL2 - Ecore_Wl2_Window *win; - - win = _wl_elm_widget_window_get(obj); - if (win) - return !!ecore_wl2_dnd_selection_get(_wl_default_seat_get(win, obj)); -#endif - return _local_elm_selection_selection_has_owner(obj); -} - -EAPI Eina_Bool -elm_cnp_clipboard_selection_has_owner(Evas_Object *win) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(win, EINA_FALSE); - return elm_selection_selection_has_owner(win); -} - -/* START - Support elm containers for Drag and Drop */ -/* START - Support elm containers for Drop */ -static int -_drop_item_container_cmp(const void *d1, - const void *d2) -{ - const Item_Container_Drop_Info *st = d1; - return (((uintptr_t) (st->obj)) - ((uintptr_t) d2)); -} - -static void -_elm_item_container_pos_cb(void *data, Evas_Object *obj, Evas_Coord x, Evas_Coord y, Elm_Xdnd_Action action) -{ /* obj is the container pointer */ - Elm_Object_Item *it = NULL; - int xposret = 0; - int yposret = 0; - - Item_Container_Drop_Info *st = - eina_list_search_unsorted(cont_drop_tg, _drop_item_container_cmp, obj); - - if (st && st->poscb) - { /* Call container drop func with specific item pointer */ - int xo = 0; - int yo = 0; - - evas_object_geometry_get(obj, &xo, &yo, NULL, NULL); - if (st->itemgetcb) - it = st->itemgetcb(obj, x+xo, y+yo, &xposret, &yposret); - - st->poscb(data, obj, it, x, y, xposret, yposret, action); - } -} - -static Eina_Bool -_elm_item_container_drop_cb(void *data, Evas_Object *obj , Elm_Selection_Data *ev) -{ /* obj is the container pointer */ - Elm_Object_Item *it = NULL; - int xposret = 0; - int yposret = 0; - - Item_Container_Drop_Info *st = - eina_list_search_unsorted(cont_drop_tg, _drop_item_container_cmp, obj); - - if (st && st->dropcb) - { /* Call container drop func with specific item pointer */ - int xo = 0; - int yo = 0; - - evas_object_geometry_get(obj, &xo, &yo, NULL, NULL); - if (st->itemgetcb) - it = st->itemgetcb(obj, ev->x+xo, ev->y+yo, &xposret, &yposret); - - return st->dropcb(data, obj, it, ev, xposret, yposret); - } - - return EINA_FALSE; -} - -static Eina_Bool -elm_drop_item_container_del_internal(Evas_Object *obj, Eina_Bool full) -{ - Item_Container_Drop_Info *st = - eina_list_search_unsorted(cont_drop_tg, _drop_item_container_cmp, obj); - - if (st) - { - // temp until st is stored inside data of obj. - _all_drop_targets_cbs_del(NULL, NULL, obj, NULL); - st->itemgetcb= NULL; - st->poscb = NULL; - st->dropcb = NULL; - - if (full) - { - cont_drop_tg = eina_list_remove(cont_drop_tg, st); - free(st); - } - - return EINA_TRUE; - } - - return EINA_FALSE; -} - -EAPI Eina_Bool -elm_drop_item_container_del(Evas_Object *obj) -{ - return elm_drop_item_container_del_internal(obj, EINA_TRUE); -} - -EAPI Eina_Bool -elm_drop_item_container_add(Evas_Object *obj, - Elm_Sel_Format format, - Elm_Xy_Item_Get_Cb itemgetcb, - Elm_Drag_State entercb, void *enterdata, - Elm_Drag_State leavecb, void *leavedata, - Elm_Drag_Item_Container_Pos poscb, void *posdata, - Elm_Drop_Item_Container_Cb dropcb, void *dropdata) -{ - Item_Container_Drop_Info *st; - - if (elm_drop_item_container_del_internal(obj, EINA_FALSE)) - { /* Updating info of existing obj */ - st = eina_list_search_unsorted(cont_drop_tg, _drop_item_container_cmp, obj); - if (!st) return EINA_FALSE; - } - else - { - st = calloc(1, sizeof(*st)); - if (!st) return EINA_FALSE; - - st->obj = obj; - cont_drop_tg = eina_list_append(cont_drop_tg, st); - } - - st->itemgetcb = itemgetcb; - st->poscb = poscb; - st->dropcb = dropcb; - elm_drop_target_add(obj, format, - entercb, enterdata, - leavecb, leavedata, - _elm_item_container_pos_cb, posdata, - _elm_item_container_drop_cb, dropdata); - - return EINA_TRUE; -} -/* END - Support elm containers for Drop */ - -/* START - Support elm containers for Drag */ -static int -_drag_item_container_cmp(const void *d1, - const void *d2) -{ - const Item_Container_Drag_Info *st = d1; - return (((uintptr_t) (st->obj)) - ((uintptr_t) d2)); -} - -static void -_cont_drag_done_cb(void *data, Evas_Object *obj EINA_UNUSED) -{ - Item_Container_Drag_Info *st = data; - elm_widget_scroll_freeze_pop(st->obj); - if (st->user_info.dragdone) - st->user_info.dragdone(st->user_info.donecbdata, dragwidget, doaccept); -} - -static Eina_Bool -_cont_obj_drag_start(void *data) -{ /* Start a drag-action when timer expires */ - cnp_debug("In\n"); - Item_Container_Drag_Info *st = data; - st->tm = NULL; - Elm_Drag_User_Info *info = &st->user_info; - if (info->dragstart) info->dragstart(info->startcbdata, st->obj); - elm_widget_scroll_freeze_push(st->obj); - evas_object_event_callback_del_full - (st->obj, EVAS_CALLBACK_MOUSE_MOVE, _cont_obj_mouse_move, st); - elm_drag_start( /* Commit the start only if data_get successful */ - st->obj, info->format, - info->data, info->action, - info->createicon, info->createdata, - info->dragpos, info->dragdata, - info->acceptcb, info->acceptdata, - _cont_drag_done_cb, st); - ELM_SAFE_FREE(info->data, free); - - return ECORE_CALLBACK_CANCEL; -} - -static void -_anim_st_free(Item_Container_Drag_Info *st) -{ /* Stops and free mem of ongoing animation */ - if (st) - { - ELM_SAFE_FREE(st->ea, ecore_animator_del); - Anim_Icon *sti; - Eo *icon; - - EINA_LIST_FREE(st->icons, sti) - { - evas_object_del(sti->o); - free(sti); - } - st->icons = NULL; - - EINA_LIST_FREE(st->user_info.icons, icon) - { - evas_object_del(icon); - } - st->user_info.icons = NULL; - } -} - -static inline Eina_List * -_anim_icons_make(Item_Container_Drag_Info *st) -{ /* Transfer user icons to animation icons list */ - Eina_List *list = NULL; - Evas_Object *o; - - EINA_LIST_FREE(st->user_info.icons, o) - { /* Now add icons to animation window */ - Anim_Icon *ast = calloc(1, sizeof(*ast)); - - if (!ast) - { - ERR("Failed to allocate memory for icon!"); - continue; - } - - evas_object_geometry_get(o, &ast->start_x, &ast->start_y, &ast->start_w, &ast->start_h); - evas_object_show(o); - ast->o = o; - list = eina_list_append(list, ast); - } - - return list; -} - -static Eina_Bool -_drag_anim_play(void *data, double pos) -{ /* Impl of the animation of icons, called on frame time */ - cnp_debug("In\n"); - Item_Container_Drag_Info *st = data; - Eina_List *l; - Anim_Icon *sti; - - if (st->ea) - { - if (pos > 0.99) - { - st->ea = NULL; /* Avoid deleting on mouse up */ - EINA_LIST_FOREACH(st->icons, l, sti) - evas_object_hide(sti->o); - - _cont_obj_drag_start(st); /* Start dragging */ - return ECORE_CALLBACK_CANCEL; - } - - Evas_Coord xm, ym; - evas_pointer_canvas_xy_get(st->e, &xm, &ym); - EINA_LIST_FOREACH(st->icons, l, sti) - { - int x, y, h, w; - w = sti->start_w + ((st->final_icon_w - sti->start_w) * pos); - h = sti->start_h + ((st->final_icon_h - sti->start_h) * pos); - x = sti->start_x - (pos * ((sti->start_x + (w/2) - xm))); - y = sti->start_y - (pos * ((sti->start_y + (h/2) - ym))); - evas_object_move(sti->o, x, y); - evas_object_resize(sti->o, w, h); - } - - return ECORE_CALLBACK_RENEW; - } - - return ECORE_CALLBACK_CANCEL; -} - -static inline Eina_Bool -_drag_anim_start(void *data) -{ /* Start default animation */ - cnp_debug("In\n"); - Item_Container_Drag_Info *st = data; - - st->tm = NULL; - /* Now we need to build an (Anim_Icon *) list */ - st->icons = _anim_icons_make(st); - if (st->user_info.createicon) - { - Evas_Object *temp_win = elm_win_add(NULL, "Temp", ELM_WIN_DND); - Evas_Object *final_icon = st->user_info.createicon(st->user_info.createdata, temp_win, NULL, NULL); - evas_object_geometry_get(final_icon, NULL, NULL, &st->final_icon_w, &st->final_icon_h); - evas_object_del(final_icon); - evas_object_del(temp_win); - } - st->ea = ecore_animator_timeline_add(st->anim_tm, _drag_anim_play, st); - - return EINA_FALSE; -} - -static Eina_Bool -_cont_obj_anim_start(void *data) -{ /* Start a drag-action when timer expires */ - cnp_debug("In\n"); - Item_Container_Drag_Info *st = data; - int xposret, yposret; /* Unused */ - Elm_Object_Item *it = (st->itemgetcb) ? - (st->itemgetcb(st->obj, st->x_down, st->y_down, &xposret, &yposret)) - : NULL; - - st->tm = NULL; - st->user_info.format = ELM_SEL_FORMAT_TARGETS; /* Default */ - st->icons = NULL; - st->user_info.data = NULL; - st->user_info.action = ELM_XDND_ACTION_COPY; /* Default */ - - if (!it) /* Failed to get mouse-down item, abort drag */ - return ECORE_CALLBACK_CANCEL; - - if (st->data_get) - { /* collect info then start animation or start dragging */ - if (st->data_get( /* Collect drag info */ - st->obj, /* The container object */ - it, /* Drag started on this item */ - &st->user_info)) - { - if (EINA_DBL_EQ(st->anim_tm, 0.0)) - _cont_obj_drag_start(st); /* Start dragging, no anim */ - else - { - if (st->user_info.icons) - { - _drag_anim_start(st); - } - else - { - // even if we don't manage the icons animation, we have - // to wait until it is finished before beginning drag. - st->tm = ecore_timer_add(st->anim_tm, _cont_obj_drag_start, st); - } - } - } - } - - return ECORE_CALLBACK_CANCEL; -} - -static void -_cont_obj_mouse_down(void *data, Evas *e, Evas_Object *obj EINA_UNUSED, void *event_info) -{ /* Launch a timer to start dragging */ - Evas_Event_Mouse_Down *ev = event_info; - cnp_debug("In - event %X\n", ev->event_flags); - if (ev->button != 1) - return; /* We only process left-click at the moment */ - - Item_Container_Drag_Info *st = data; - st->e = e; - st->x_down = ev->canvas.x; - st->y_down = ev->canvas.y; - - evas_object_event_callback_add(st->obj, EVAS_CALLBACK_MOUSE_UP, - _cont_obj_mouse_up, st); - - ecore_timer_del(st->tm); - - if (st->tm_to_drag) - { - st->tm = ecore_timer_add(st->tm_to_drag, _cont_obj_anim_start, st); - evas_object_event_callback_add(st->obj, EVAS_CALLBACK_MOUSE_MOVE, - _cont_obj_mouse_move, st); - } - else - _cont_obj_anim_start(st); -} - -static Eina_Bool elm_drag_item_container_del_internal(Evas_Object *obj, Eina_Bool full); - -static void -_abort_drag(Evas_Object *obj, Item_Container_Drag_Info *st) -{ - evas_object_event_callback_del_full - (st->obj, EVAS_CALLBACK_MOUSE_MOVE, _cont_obj_mouse_move, st); - evas_object_event_callback_del_full - (st->obj, EVAS_CALLBACK_MOUSE_UP, _cont_obj_mouse_up, st); - elm_drag_item_container_del_internal(obj, EINA_FALSE); - - ELM_SAFE_FREE(st->tm, ecore_timer_del); - - _anim_st_free(st); -} - -static void -_cont_obj_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) -{ /* Cancel any drag waiting to start on timeout */ - cnp_debug("In\n"); - Item_Container_Drag_Info *st = data; - Evas_Event_Mouse_Move *ev = event_info; - - if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) - { - cnp_debug("event on hold - have to cancel DnD\n"); - - _abort_drag(obj, st); - st = NULL; - } - - if (st && evas_device_class_get(ev->dev) == EVAS_DEVICE_CLASS_TOUCH) - { - int dx = ev->cur.canvas.x - st->x_down, dy = ev->cur.canvas.y - st->y_down; - int finger_size = elm_config_finger_size_get(); - if ((dx * dx + dy * dy > finger_size * finger_size)) - { - cnp_debug("mouse moved too much - have to cancel DnD\n"); - - _abort_drag(obj, st); - st = NULL; - } - } - cnp_debug("Out\n"); -} - -static void -_cont_obj_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) -{ /* Cancel any drag waiting to start on timeout */ - Item_Container_Drag_Info *st = data; - - cnp_debug("In\n"); - if (((Evas_Event_Mouse_Up *)event_info)->button != 1) - return; /* We only process left-click at the moment */ - - evas_object_event_callback_del_full - (st->obj, EVAS_CALLBACK_MOUSE_MOVE, _cont_obj_mouse_move, st); - evas_object_event_callback_del_full - (st->obj, EVAS_CALLBACK_MOUSE_UP, _cont_obj_mouse_up, st); - - ELM_SAFE_FREE(st->tm, ecore_timer_del); - - _anim_st_free(st); -} - -static Eina_Bool -elm_drag_item_container_del_internal(Evas_Object *obj, Eina_Bool full) -{ - Item_Container_Drag_Info *st = - eina_list_search_unsorted(cont_drag_tg, _drag_item_container_cmp, obj); - - if (st) - { - ELM_SAFE_FREE(st->tm, ecore_timer_del); /* Cancel drag-start timer */ - - if (st->ea) /* Cancel ongoing default animation */ - _anim_st_free(st); - - if (full) - { - st->itemgetcb = NULL; - st->data_get = NULL; - evas_object_event_callback_del_full - (obj, EVAS_CALLBACK_MOUSE_DOWN, _cont_obj_mouse_down, st); - - cont_drag_tg = eina_list_remove(cont_drag_tg, st); - ELM_SAFE_FREE(st->user_info.data, free); - free(st); - } - - return EINA_TRUE; - } - return EINA_FALSE; -} - -EAPI Eina_Bool -elm_drag_item_container_del(Evas_Object *obj) -{ - return elm_drag_item_container_del_internal(obj, EINA_TRUE); -} - -EAPI Eina_Bool -elm_drag_item_container_add(Evas_Object *obj, double anim_tm, double tm_to_drag, Elm_Xy_Item_Get_Cb itemgetcb, Elm_Item_Container_Data_Get_Cb data_get) -{ - Item_Container_Drag_Info *st; - - if (elm_drag_item_container_del_internal(obj, EINA_FALSE)) - { /* Updating info of existing obj */ - st = eina_list_search_unsorted(cont_drag_tg, _drag_item_container_cmp, obj); - if (!st) return EINA_FALSE; - } - else - { - st = calloc(1, sizeof(*st)); - if (!st) return EINA_FALSE; - - st->obj = obj; - cont_drag_tg = eina_list_append(cont_drag_tg, st); - - /* Register for mouse callback for container to start/abort drag */ - evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN, - _cont_obj_mouse_down, st); - } - - st->tm = NULL; - st->anim_tm = anim_tm; - st->tm_to_drag = tm_to_drag; - st->itemgetcb = itemgetcb; - st->data_get = data_get; - - return EINA_TRUE; -} -/* END - Support elm containers for Drag */ -/* END - Support elm containers for Drag and Drop */ - -EAPI Eina_Bool -elm_drag_cancel(Evas_Object *obj) -{ -#ifdef HAVE_ELEMENTARY_X - Ecore_X_Window xwin = _x11_elm_widget_xwin_get(obj); - if (xwin) - { - ecore_x_pointer_ungrab(); - ELM_SAFE_FREE(handler_up, ecore_event_handler_del); - ELM_SAFE_FREE(handler_status, ecore_event_handler_del); - ecore_x_dnd_abort(xwin); - if (dragwidget) - { - if (elm_widget_is(dragwidget)) - { - Evas_Object *win = elm_widget_top_get(dragwidget); - if (win && efl_isa(win, EFL_UI_WIN_CLASS)) - efl_event_callback_del(win, EFL_UI_WIN_EVENT_ROTATION_CHANGED, _x11_win_rotation_changed_cb, dragwin); - } - } - goto end; - } -#endif -#ifdef HAVE_ELEMENTARY_WL2 - Ecore_Wl2_Window *win; - - win = _wl_elm_widget_window_get(obj); - if (win) - ecore_wl2_dnd_drag_end(_wl_default_seat_get(win, obj)); -#endif - -end: - ELM_SAFE_FREE(dragwin, evas_object_del); - dragdonecb = NULL; - dragacceptcb = NULL; - dragposcb = NULL; - dragwidget = NULL; - doaccept = EINA_FALSE; - return EINA_TRUE; -} -