summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThiep Ha <thiepha@gmail.com>2018-01-09 18:50:23 +0900
committerThiep Ha <thiepha@gmail.com>2018-01-11 17:56:24 +0900
commite88bbaa1e314751e5c1a04dec7f1f179188428ae (patch)
tree0964c6cd19b3888c026980d96441fea9441d176b
parent35339504b0db553083abeccd0bf5c1dcd05b4acc (diff)
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.
-rw-r--r--src/Makefile_Elementary.am1
-rw-r--r--src/lib/elementary/efl_selection.c241
-rw-r--r--src/lib/elementary/efl_selection_manager.c90
-rw-r--r--src/lib/elementary/efl_ui_dnd.c678
-rw-r--r--src/lib/elementary/elm_cnp.c5851
5 files changed, 963 insertions, 5898 deletions
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 = \
618 lib/elementary/efl_ui_calendar.c \ 618 lib/elementary/efl_ui_calendar.c \
619 lib/elementary/efl_ui_check.c \ 619 lib/elementary/efl_ui_check.c \
620 lib/elementary/elm_clock.c \ 620 lib/elementary/elm_clock.c \
621 lib/elementary/elm_cnp.c \
622 lib/elementary/elm_code_line.c \ 621 lib/elementary/elm_code_line.c \
623 lib/elementary/elm_code_text.c \ 622 lib/elementary/elm_code_text.c \
624 lib/elementary/elm_code_indent.c \ 623 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,
59} 59}
60 60
61 61
62////////// Support legacy APIs
63
64//TODO: Clear this list (when sel_man is deleted)
65Eina_List *lost_cb_list = NULL;
66
67#ifdef HAVE_ELEMENTARY_WL2
68static Ecore_Wl2_Window *
69_wl_window_get(const Evas_Object *obj)
70{
71 Evas_Object *top;
72 Ecore_Wl2_Window *win = NULL;
73
74 if (elm_widget_is(obj))
75 {
76 top = elm_widget_top_get(obj);
77 if (!top) top = elm_widget_top_get(elm_widget_parent_widget_get(obj));
78 if (top && (efl_isa(top, EFL_UI_WIN_CLASS)))
79 win = elm_win_wl_window_get(top);
80 }
81 if (!win)
82 {
83 Ecore_Evas *ee;
84 Evas *evas;
85 const char *engine_name;
86
87 if (!(evas = evas_object_evas_get(obj)))
88 return NULL;
89 if (!(ee = ecore_evas_ecore_evas_get(evas)))
90 return NULL;
91
92 engine_name = ecore_evas_engine_name_get(ee);
93 if (!strcmp(engine_name, ELM_BUFFER))
94 {
95 ee = ecore_evas_buffer_ecore_evas_parent_get(ee);
96 if (!ee) return NULL;
97 engine_name = ecore_evas_engine_name_get(ee);
98 }
99 if (!strncmp(engine_name, "wayland", sizeof("wayland") - 1))
100 {
101 /* In case the engine is not a buffer, we want to check once. */
102 win = ecore_evas_wayland2_window_get(ee);
103 if (!win) return NULL;
104 }
105 }
106
107 return win;
108}
109
110int _wl_default_seat_id_get(Evas_Object *obj)
111{
112 Ecore_Wl2_Window *win = _wl_window_get(obj);
113 Eo *seat, *parent2, *ewin;
114
115 if (obj)
116 {
117 Eo *top = elm_widget_top_get(obj);
118 if (efl_isa(top, EFL_UI_WIN_INLINED_CLASS))
119 {
120 parent2 = efl_ui_win_inlined_parent_get(top);
121 if (parent2) obj = elm_widget_top_get(parent2) ?: parent2;
122 }
123 /* fake win means canvas seat id will not match protocol seat id */
124 ewin = elm_win_get(obj);
125 if (elm_win_type_get(ewin) == ELM_WIN_FAKE) obj = NULL;
126 }
127
128 if (!obj)
129 {
130 Ecore_Wl2_Input *input;
131 Eina_Iterator *it;
132
133 it = ecore_wl2_display_inputs_get(ecore_wl2_window_display_get(win));
134 EINA_ITERATOR_FOREACH(it, input) break;
135 eina_iterator_free(it);
136 if (input)
137 ecore_wl2_input_seat_id_get(input);
138 }
139
140 seat = evas_default_device_get(evas_object_evas_get(obj), EFL_INPUT_DEVICE_TYPE_SEAT);
141 EINA_SAFETY_ON_NULL_RETURN_VAL(seat, 1);
142 return evas_device_seat_id_get(seat);
143}
144#endif
145
146typedef struct _Cnp_Data_Cb_Wrapper Cnp_Data_Cb_Wrapper;
147struct _Cnp_Data_Cb_Wrapper
148{
149 void *udata;
150 Elm_Drop_Cb datacb;
151};
152
153static void
154_selection_data_ready_cb(void *data, Efl_Object *obj, Efl_Selection_Data *seldata)
155{
156 printf("obj: %p, data: %s, length: %zd\n", obj, (char *)seldata->data.mem, seldata->data.len);
157 Cnp_Data_Cb_Wrapper *wdata = data;
158 if (!wdata) return;
159 Elm_Selection_Data ddata;
160
161 ddata.data = calloc(1, seldata->data.len + 1);
162 if (!ddata.data) return;
163 ddata.data = memcpy(ddata.data, seldata->data.mem, seldata->data.len);
164 ddata.len = seldata->data.len;
165 ddata.x = seldata->pos.x;
166 ddata.y = seldata->pos.y;
167 ddata.format = seldata->format;
168 ddata.action = seldata->action;
169 wdata->datacb(wdata->udata, obj, &ddata);
170 free(ddata.data);
171}
172
173typedef struct _Sel_Lost_Data Sel_Lost_Data;
174struct _Sel_Lost_Data
175{
176 const Evas_Object *obj;
177 Elm_Sel_Type type;
178 void *udata;
179 Elm_Selection_Loss_Cb loss_cb;
180};
181
182static Eina_Value
183_selection_lost_cb(void *data, const Eina_Value value)
184{
185 Eina_List *l, *l2;
186 Sel_Lost_Data *ldata, *ldata2;
187
188 ldata = data;
189 EINA_LIST_FOREACH_SAFE(lost_cb_list, l, l2, ldata2)
190 {
191 if ((ldata->obj == ldata2->obj) &&
192 (ldata->type == ldata2->type))
193 {
194 ldata2->loss_cb(ldata2->udata, ldata2->type);
195 lost_cb_list = eina_list_remove(lost_cb_list, ldata2);
196 }
197 }
198 free(ldata);
199
200 return value;
201}
202
203EAPI Eina_Bool
204elm_cnp_selection_get(const Evas_Object *obj, Elm_Sel_Type type,
205 Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata)
206{
207 int seatid = 1;
208 Eo *sel_man = _selection_manager_get((Evas_Object *)obj);
209 Cnp_Data_Cb_Wrapper *wdata = calloc(1, sizeof(Cnp_Data_Cb_Wrapper));
210
211 if (!wdata) return EINA_FALSE;
212
213#ifdef HAVE_ELEMENTARY_WL2
214 seatid = _wl_default_seat_id_get(obj);
215#endif
216 wdata->udata = udata;
217 wdata->datacb = datacb;
218 efl_selection_manager_selection_get(sel_man, (Evas_Object *)obj, type, format,
219 wdata, _selection_data_ready_cb, NULL, seatid);
220 return EINA_TRUE;
221}
222
223EAPI Eina_Bool
224elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type type,
225 Elm_Sel_Format format, const void *selbuf, size_t buflen)
226{
227 int seatid = 1;
228 Eina_Future *f;
229 Sel_Lost_Data *ldata;
230 Eo *sel_man = _selection_manager_get(obj);
231 Eina_Slice data;
232
233 ldata = calloc(1, sizeof(Sel_Lost_Data));
234 if (!ldata) return EINA_FALSE;
235 data.mem = selbuf;
236 data.len = buflen;
237#ifdef HAVE_ELEMENTARY_WL2
238 seatid = _wl_default_seat_id_get(obj);
239#endif
240 f = efl_selection_manager_selection_set(sel_man, obj, type, format, data, seatid);
241
242 ldata->obj = obj;
243 ldata->type = type;
244 eina_future_then_easy(f, _selection_lost_cb, NULL, NULL, EINA_VALUE_TYPE_UINT, ldata);
245
246 return EINA_TRUE;
247}
248
249EAPI Eina_Bool
250elm_object_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type type)
251{
252 int seatid = 1;
253 Eo *sel_man = _selection_manager_get((Evas_Object *)obj);
254
255#ifdef HAVE_ELEMENTARY_WL2
256 seatid = _wl_default_seat_id_get(obj);
257#endif
258 efl_selection_manager_selection_clear(sel_man, obj, type, seatid);
259
260 return EINA_TRUE;
261}
262
263EAPI void
264elm_cnp_selection_loss_callback_set(Evas_Object *obj, Elm_Sel_Type type,
265 Elm_Selection_Loss_Cb func, const void *data)
266{
267 Sel_Lost_Data *ldata = calloc(1, sizeof(Sel_Lost_Data));
268 if (!ldata) return;
269 ldata->obj = obj;
270 ldata->type = type;
271 ldata->udata = (void *)data;
272 ldata->loss_cb = func;
273 lost_cb_list = eina_list_append(lost_cb_list, ldata);
274}
275
276EAPI Eina_Bool
277elm_selection_selection_has_owner(Evas_Object *obj)
278{
279 int seatid = 1;
280 Eo *sel_man = _selection_manager_get((Evas_Object *)obj);
281
282#ifdef HAVE_ELEMENTARY_WL2
283 seatid = _wl_default_seat_id_get(obj);
284#endif
285
286 return efl_selection_manager_selection_has_owner(sel_man, obj,
287 EFL_SELECTION_TYPE_CLIPBOARD, seatid);
288}
289
290EAPI Eina_Bool
291elm_cnp_clipboard_selection_has_owner(Evas_Object *obj)
292{
293 int seatid = 1;
294 Eo *sel_man = _selection_manager_get((Evas_Object *)obj);
295
296#ifdef HAVE_ELEMENTARY_WL2
297 seatid = _wl_default_seat_id_get(obj);
298#endif
299 return efl_selection_manager_selection_has_owner(sel_man, obj,
300 EFL_SELECTION_TYPE_CLIPBOARD, seatid);
301}
302
62#include "efl_selection.eo.c" 303#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 @@
19# define sel_debug(x...) do { } while (0) 19# define sel_debug(x...) do { } while (0)
20#endif 20#endif
21 21
22static void _set_selection_list(Sel_Manager_Selection *sel_list, Sel_Manager_Seat_Selection *seat_sel);
23static void _anim_data_free(Sel_Manager_Drag_Container *dc); 22static void _anim_data_free(Sel_Manager_Drag_Container *dc);
24static void _cont_obj_mouse_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info); 23static void _cont_obj_mouse_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
25static void _cont_obj_mouse_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info); 24static 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
30void 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); 29void 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);
31 30
32#ifdef HAVE_ELEMENTARY_X 31#ifdef HAVE_ELEMENTARY_X
32static void _set_selection_list(Sel_Manager_Selection *sel_list, Sel_Manager_Seat_Selection *seat_sel);
33static Ecore_X_Atom _x11_dnd_action_rev_map(Efl_Selection_Action action); 33static Ecore_X_Atom _x11_dnd_action_rev_map(Efl_Selection_Action action);
34static Ecore_X_Window _x11_xwin_get(const Evas_Object *obj); 34static Ecore_X_Window _x11_xwin_get(const Evas_Object *obj);
35#endif 35#endif
36 36
37#ifdef HAVE_ELEMENTARY_WL2 37#ifdef HAVE_ELEMENTARY_WL2
38static Ecore_Wl2_Window *_wl_window_get(const Evas_Object *obj); 38static Ecore_Wl2_Window *_wl_window_get(const Evas_Object *obj);
39static Ecore_Wl2_Input *_wl_seat_get(Ecore_Wl2_Window *win, const Evas_Object *obj, unsigned int seat_id); 39static Ecore_Wl2_Input *_wl_seat_get(Ecore_Wl2_Window *win, Evas_Object *obj, unsigned int seat_id);
40#endif
41
42#ifdef HAVE_ELEMENTARY_WIN32
43static void _set_selection_list(Sel_Manager_Selection *sel_list, Sel_Manager_Seat_Selection *seat_sel);
40#endif 44#endif
41 45
42static inline void 46static inline void
@@ -157,6 +161,37 @@ _sel_manager_seat_selection_init(Efl_Selection_Manager_Data *pd, unsigned int se
157 return seat_sel; 161 return seat_sel;
158} 162}
159 163
164static void
165_sel_manager_promise_cancel(void *data, const Eina_Promise *dead_future EINA_UNUSED)
166{
167 Sel_Manager_Selection_Lost *sel_lost = data;
168 //FIXME: remove from sel_lost_list in seat_sel
169 free(sel_lost);
170}
171
172static inline Eina_Future *
173_update_sel_lost_list(Efl_Object *obj, Efl_Selection_Type type,
174 Sel_Manager_Seat_Selection *seat_sel)
175{
176 Eina_Promise *p;
177 Sel_Manager_Selection_Lost *sel_lost;
178
179 sel_lost = calloc(1, sizeof(Sel_Manager_Selection_Lost));
180 if (!sel_lost)
181 return NULL;
182 sel_lost->request = obj;
183 sel_lost->type = type;
184 seat_sel->sel_lost_list = eina_list_append(seat_sel->sel_lost_list, sel_lost);
185
186 p = eina_promise_new(efl_loop_future_scheduler_get(obj),
187 _sel_manager_promise_cancel, NULL);
188 eina_promise_data_set(p, sel_lost);
189 if (!p) return NULL;
190 sel_lost->promise = p;
191
192 return eina_future_new(p);
193}
194
160/* TODO: this should not be an actual tempfile, but rather encode the object 195/* TODO: this should not be an actual tempfile, but rather encode the object
161 * as http://dataurl.net/ if it's an image or similar. Evas should support 196 * as http://dataurl.net/ if it's an image or similar. Evas should support
162 * decoding it as memfile. */ 197 * decoding it as memfile. */
@@ -901,7 +936,6 @@ _x11_selection_clear(void *data, int type EINA_UNUSED, void *event)
901 Eina_List *l, *l_next; 936 Eina_List *l, *l_next;
902 Sel_Manager_Selection_Lost *sel_lost; 937 Sel_Manager_Selection_Lost *sel_lost;
903 unsigned int i; 938 unsigned int i;
904 ERR("In");
905 939
906 seat_sel = _sel_manager_seat_selection_get(pd, 1); 940 seat_sel = _sel_manager_seat_selection_get(pd, 1);
907 if (!seat_sel) 941 if (!seat_sel)
@@ -1082,37 +1116,6 @@ _x11_text_converter(char *target, void *data, int size EINA_UNUSED, void **data_
1082 return EINA_TRUE; 1116 return EINA_TRUE;
1083} 1117}
1084 1118
1085static void
1086_sel_manager_promise_cancel(void *data, const Eina_Promise *dead_future EINA_UNUSED)
1087{
1088 Sel_Manager_Selection_Lost *sel_lost = data;
1089 //FIXME: remove from sel_lost_list in seat_sel
1090 free(sel_lost);
1091}
1092
1093static inline Eina_Future *
1094_update_sel_lost_list(Efl_Object *obj, Efl_Selection_Type type,
1095 Sel_Manager_Seat_Selection *seat_sel)
1096{
1097 Eina_Promise *p;
1098 Sel_Manager_Selection_Lost *sel_lost;
1099
1100 sel_lost = calloc(1, sizeof(Sel_Manager_Selection_Lost));
1101 if (!sel_lost)
1102 return NULL;
1103 sel_lost->request = obj;
1104 sel_lost->type = type;
1105 seat_sel->sel_lost_list = eina_list_append(seat_sel->sel_lost_list, sel_lost);
1106
1107 p = eina_promise_new(efl_loop_future_scheduler_get(obj),
1108 _sel_manager_promise_cancel, NULL);
1109 eina_promise_data_set(p, sel_lost);
1110 if (!p) return NULL;
1111 sel_lost->promise = p;
1112
1113 return eina_future_new(p);
1114}
1115
1116static Eina_Future * 1119static Eina_Future *
1117_x11_efl_sel_manager_selection_set(Efl_Selection_Manager_Data *pd, Efl_Object *owner, 1120_x11_efl_sel_manager_selection_set(Efl_Selection_Manager_Data *pd, Efl_Object *owner,
1118 Efl_Selection_Type type, Efl_Selection_Format format, Eina_Slice data, 1121 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
1138 sel->format = format; 1141 sel->format = format;
1139 1142
1140 sel->set(xwin, &sel, sizeof(&sel)); 1143 sel->set(xwin, &sel, sizeof(&sel));
1141 sel_debug("data: %p (%ld)", &sel, sizeof(&sel)); 1144 sel_debug("data: %p (%zu)", &sel, sizeof(&sel));
1142 1145
1143 return _update_sel_lost_list(owner, type, seat_sel); 1146 return _update_sel_lost_list(owner, type, seat_sel);
1144} 1147}
@@ -1964,7 +1967,6 @@ _x11_sel_manager_drop_target_add(Efl_Selection_Manager_Data *pd, Efl_Object *tar
1964 Efl_Selection_Format format, Ecore_X_Window xwin, 1967 Efl_Selection_Format format, Ecore_X_Window xwin,
1965 unsigned int seat) 1968 unsigned int seat)
1966{ 1969{
1967 ERR("In");
1968 Sel_Manager_Dropable *dropable = NULL; 1970 Sel_Manager_Dropable *dropable = NULL;
1969 Eina_List *l; 1971 Eina_List *l;
1970 Eina_Bool have_drop_list = EINA_FALSE; 1972 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 *
2076} 2078}
2077 2079
2078static void 2080static void
2079_wl_efl_sel_manager_drag_start(Eo *obj, Efl_Selection_Manager_Data *pd, Efl_Object *drag_obj, 2081_wl_efl_sel_manager_drag_start(Eo *obj EINA_UNUSED, Efl_Selection_Manager_Data *pd, Efl_Object *drag_obj,
2080 Efl_Selection_Format format, Eina_Slice data, 2082 Efl_Selection_Format format, Eina_Slice data,
2081 Efl_Selection_Action action, void *icon_func_data, 2083 Efl_Selection_Action action, void *icon_func_data,
2082 Efl_Dnd_Drag_Icon_Create icon_func, Eina_Free_Cb icon_func_free_cb, 2084 Efl_Dnd_Drag_Icon_Create icon_func, Eina_Free_Cb icon_func_free_cb EINA_UNUSED,
2083 Ecore_Wl2_Window *win, unsigned int seat) 2085 Ecore_Wl2_Window *win, unsigned int seat)
2084{ 2086{
2085 Ecore_Evas *ee; 2087 Ecore_Evas *ee;
@@ -2481,11 +2483,11 @@ _wl_efl_sel_manager_selection_set(Efl_Selection_Manager_Data *pd,
2481 return _update_sel_lost_list(owner, type, seat_sel); 2483 return _update_sel_lost_list(owner, type, seat_sel);
2482} 2484}
2483 2485
2484static void 2486/*static void
2485_wl_selection_changed_free(void *data, void *ev EINA_UNUSED) 2487_wl_selection_changed_free(void *data, void *ev EINA_UNUSED)
2486{ 2488{
2487 ecore_wl2_display_disconnect(data); 2489 ecore_wl2_display_disconnect(data);
2488} 2490}*/
2489 2491
2490static Eina_Bool 2492static Eina_Bool
2491_wl_selection_changed(void *data, int type EINA_UNUSED, void *event) 2493_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)
2622} 2624}
2623 2625
2624static Ecore_Wl2_Input * 2626static Ecore_Wl2_Input *
2625_wl_seat_get(Ecore_Wl2_Window *win, const Evas_Object *obj, unsigned int seat_id) 2627_wl_seat_get(Ecore_Wl2_Window *win, Evas_Object *obj, unsigned int seat_id)
2626{ 2628{
2627 Eo *seat, *parent2, *ewin; 2629 Eo *seat, *parent2, *ewin;
2628 Ecore_Wl2_Input *input = NULL; 2630 Ecore_Wl2_Input *input = NULL;
@@ -2719,7 +2721,6 @@ _wl_selection_receive(void *data, int type EINA_UNUSED, void *event)
2719{ 2721{
2720 Ecore_Wl2_Event_Offer_Data_Ready *ev = event; 2722 Ecore_Wl2_Event_Offer_Data_Ready *ev = event;
2721 Sel_Manager_Selection *sel = data; 2723 Sel_Manager_Selection *sel = data;
2722 ERR("in");
2723 2724
2724 if (sel->sel_offer != ev->offer) return ECORE_CALLBACK_PASS_ON; 2725 if (sel->sel_offer != ev->offer) return ECORE_CALLBACK_PASS_ON;
2725 2726
@@ -2783,7 +2784,7 @@ _wl_efl_sel_manager_selection_get(const Efl_Object *request, Efl_Selection_Manag
2783 sel->data_func = data_func; 2784 sel->data_func = data_func;
2784 sel->data_func_free_cb = data_func_free_cb; 2785 sel->data_func_free_cb = data_func_free_cb;
2785 2786
2786 input = _wl_seat_get(win, request, seat_sel->seat); 2787 input = _wl_seat_get(win, (Efl_Object *)request, seat_sel->seat);
2787 offer = ecore_wl2_dnd_selection_get(input); 2788 offer = ecore_wl2_dnd_selection_get(input);
2788 2789
2789 //there can be no selection available 2790 //there can be no selection available
@@ -4279,7 +4280,6 @@ _drag_anim_play(void *data, double pos)
4279{ 4280{
4280 Sel_Manager_Drag_Container *dc = data; 4281 Sel_Manager_Drag_Container *dc = data;
4281 4282
4282 ERR("In");
4283 if (dc->animator) 4283 if (dc->animator)
4284 { 4284 {
4285 Eina_List *l; 4285 Eina_List *l;
@@ -4317,7 +4317,6 @@ _drag_anim_play(void *data, double pos)
4317static inline void 4317static inline void
4318_drag_anim_start(Sel_Manager_Drag_Container *dc) 4318_drag_anim_start(Sel_Manager_Drag_Container *dc)
4319{ 4319{
4320 ERR("In");
4321 4320
4322 dc->timer = NULL; 4321 dc->timer = NULL;
4323 if (dc->icon_func) 4322 if (dc->icon_func)
@@ -4904,7 +4903,6 @@ EOLIAN static void
4904_efl_selection_manager_container_drop_item_del(Eo *obj EINA_UNUSED, Efl_Selection_Manager_Data *pd, 4903_efl_selection_manager_container_drop_item_del(Eo *obj EINA_UNUSED, Efl_Selection_Manager_Data *pd,
4905 Efl_Object *cont, unsigned int seat EINA_UNUSED) 4904 Efl_Object *cont, unsigned int seat EINA_UNUSED)
4906{ 4905{
4907 ERR("In");
4908 _drop_item_container_del(pd, cont, EINA_TRUE); 4906 _drop_item_container_del(pd, cont, EINA_TRUE);
4909} 4907}
4910 4908
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_
132 efl_selection_manager_container_drop_item_del(sel_man, obj, seat); 132 efl_selection_manager_container_drop_item_del(sel_man, obj, seat);
133} 133}
134 134
135
136///////////
137typedef struct _Dnd_Icon_Create Dnd_Icon_Create;
138typedef struct _Dnd_Drag_Pos Dnd_Drag_Pos;
139typedef struct _Dnd_Drag_Accept Dnd_Drag_Accept;
140typedef struct _Dnd_Drag_Done Dnd_Drag_Done;
141typedef struct _Dnd_Drag_State Dnd_Drag_State;
142typedef struct _Dnd_Drop Dnd_Drop;
143typedef struct _Dnd_Cont_Drag_Pos Dnd_Cont_Drag_Pos;
144typedef struct _Dnd_Cont_Drop Dnd_Cont_Drop;
145typedef struct _Item_Container_Drag_Info Item_Container_Drag_Info;
146
147struct _Dnd_Icon_Create
148{
149 void *icon_data;
150 Elm_Drag_Icon_Create_Cb icon_cb;
151};
152
153struct _Dnd_Drag_Pos
154{
155 void *pos_data;
156 Elm_Drag_Pos pos_cb;
157};
158
159struct _Dnd_Drag_Accept
160{
161 void *accept_data;
162 Elm_Drag_Accept accept_cb;
163};
164
165struct _Dnd_Drag_Done
166{
167 void *done_data;
168 Elm_Drag_State done_cb;
169
170 //for deleting
171 Dnd_Drag_Pos *pos;
172 Dnd_Drag_Accept *accept;
173};
174
175struct _Dnd_Drag_State
176{
177 void *state_data;
178 Elm_Drag_State state_cb;
179};
180
181struct _Dnd_Drop
182{
183 Efl_Object *obj;
184 Elm_Sel_Format format;
185 void *drop_data;
186 Elm_Drop_Cb drop_cb;
187
188 //for deleting
189 Dnd_Drag_State *enter;
190 Dnd_Drag_State *leave;
191 Dnd_Drag_Pos *pos;
192};
193
194struct _Dnd_Cont_Drag_Pos
195{
196 void *pos_data;
197 Elm_Drag_Item_Container_Pos pos_cb;
198 Elm_Xy_Item_Get_Cb item_get_cb;
199};
200
201struct _Dnd_Cont_Drop
202{
203 Efl_Object *obj;
204 Elm_Sel_Format format;
205 void *drop_data;
206 Elm_Drop_Item_Container_Cb drop_cb;
207 Elm_Xy_Item_Get_Cb item_get_cb;
208
209 //for deleting
210 Dnd_Drag_State *enter;
211 Dnd_Drag_State *leave;
212 Dnd_Cont_Drag_Pos *pos;
213};
214
215struct _Item_Container_Drag_Info
216{
217 Elm_Drag_User_Info user_info;
218 Elm_Object_Item *it;
219 Elm_Item_Container_Data_Get_Cb data_get_cb;
220 Elm_Xy_Item_Get_Cb item_get_cb;
221};
222
223static Efl_Object *
224_dnd_icon_create_cb(void *data, Efl_Object *win, Efl_Object *drag_obj EINA_UNUSED, Eina_Position2D *pos_ret)
225{
226 Dnd_Icon_Create *ic = data;
227 Efl_Object *ret = ic->icon_cb(ic->icon_data, win, &pos_ret->x, &pos_ret->y);
228
229 free(ic);
230 return ret;
231}
232
233static void
234_dnd_drag_pos_cb(void *data, const Efl_Event *event)
235{
236 Dnd_Drag_Pos *pos = data;
237 Efl_Dnd_Drag_Pos *ddata = event->info;
238
239 if (pos->pos_cb)
240 pos->pos_cb(pos->pos_data, event->object, ddata->pos.x, ddata->pos.y,
241 ddata->action);
242}
243
244static void
245_dnd_drag_accept_cb(void *data, const Efl_Event *event)
246{
247 Dnd_Drag_Accept *accept = data;
248
249 if (accept->accept_cb)
250 accept->accept_cb(accept->accept_data, event->object, *(Eina_Bool *)event->info);
251}
252
253static void
254_dnd_drag_done_cb(void *data, const Efl_Event *event)
255{
256 Dnd_Drag_Done *done = data;
257
258 if (done->done_cb)
259 done->done_cb(done->done_data, event->object);
260
261 efl_event_callback_del(event->object, EFL_UI_DND_EVENT_DRAG_POS,
262 _dnd_drag_pos_cb, done->pos);
263 efl_event_callback_del(event->object, EFL_UI_DND_EVENT_DRAG_ACCEPT,
264 _dnd_drag_accept_cb, done->accept);
265 efl_event_callback_del(event->object, EFL_UI_DND_EVENT_DRAG_DONE,
266 _dnd_drag_done_cb, done);
267 free(done->pos);
268 free(done->accept);
269 free(done);
270}
271
272static void
273_dnd_drag_enter_leave_cb(void *data, const Efl_Event *event)
274{
275 Dnd_Drag_State *state = data;
276
277 if (state->state_cb)
278 state->state_cb(state->state_data, event->object);
279}
280
281static void
282_dnd_drop_cb(void *data, const Efl_Event *event)
283{
284 Dnd_Drop *drop = data;
285 Efl_Selection_Data *org_ddata = event->info;
286 Elm_Selection_Data ddata;
287
288 ddata.x = org_ddata->pos.x;
289 ddata.y = org_ddata->pos.y;
290 ddata.format = org_ddata->format;
291 ddata.action = org_ddata->action;
292 ddata.data = calloc(1, org_ddata->data.len);
293 if (!ddata.data) return;
294 ddata.data = memcpy(ddata.data, org_ddata->data.mem, org_ddata->data.len);
295 ddata.len = org_ddata->data.len;
296 if (drop->drop_cb)
297 drop->drop_cb(drop->drop_data, event->object, &ddata);
298 free(ddata.data);
299}
300
301EAPI Eina_Bool
302elm_drag_start(Evas_Object *obj, Elm_Sel_Format format, const char *data,
303 Elm_Xdnd_Action action,
304 Elm_Drag_Icon_Create_Cb icon_create_cb, void *icon_create_data,
305 Elm_Drag_Pos drag_pos_cb, void *drag_pos_data,
306 Elm_Drag_Accept drag_accept_cb, void *drag_accept_data,
307 Elm_Drag_State drag_done_cb, void *drag_done_data)
308{
309 Eo *sel_man = _selection_manager_get(obj);
310 int seatid = 1;
311 Eina_Slice sl;
312 Dnd_Drag_Pos *pos = calloc(1, sizeof(Dnd_Drag_Pos));
313 Dnd_Drag_Accept *accept = calloc(1, sizeof(Dnd_Drag_Accept));
314 Dnd_Drag_Done *done = calloc(1, sizeof(Dnd_Drag_Done));
315 Dnd_Icon_Create *ic = calloc(1, sizeof(Dnd_Icon_Create));
316 if (!pos || !accept || !done || !ic) return EINA_FALSE;
317
318 pos->pos_data = drag_pos_data;
319 pos->pos_cb = drag_pos_cb;
320
321 accept->accept_data = drag_accept_data;
322 accept->accept_cb = drag_accept_cb;
323
324 done->done_data = drag_done_data;
325 done->done_cb = drag_done_cb;
326 done->pos = pos;
327 done->accept = accept;
328
329 efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_POS, _dnd_drag_pos_cb, pos);
330 efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_ACCEPT, _dnd_drag_accept_cb, accept);
331 efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_DONE, _dnd_drag_done_cb, done);
332 sl.mem = data;
333 sl.len = strlen(data);
334#ifdef HAVE_ELEMENTARY_WL2
335 seatid = _wl_default_seat_id_get(obj);
336#endif
337
338 ic->icon_data = icon_create_data;
339 ic->icon_cb = icon_create_cb;
340 efl_selection_manager_drag_start(sel_man, obj, format, sl, action,
341 ic, _dnd_icon_create_cb, NULL, seatid);
342
343 return EINA_TRUE;
344}
345
346EAPI Eina_Bool
347elm_drag_action_set(Evas_Object *obj, Elm_Xdnd_Action action)
348{
349 Eo *sel_man = _selection_manager_get(obj);
350 int seatid = 1;
351
352#ifdef HAVE_ELEMENTARY_WL2
353 seatid = _wl_default_seat_id_get(obj);
354#endif
355 efl_selection_manager_drag_action_set(sel_man, obj, action, seatid);
356
357 return EINA_TRUE;
358}
359
360EAPI Eina_Bool
361elm_drag_cancel(Evas_Object *obj)
362{
363 Eo *sel_man = _selection_manager_get(obj);
364 int seatid = 1;
365
366#ifdef HAVE_ELEMENTARY_WL2
367 seatid = _wl_default_seat_id_get(obj);
368#endif
369
370 efl_selection_manager_drag_cancel(sel_man, obj, seatid);
371
372 return EINA_TRUE;
373}
374
375static void
376_drop_obj_del_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
377{
378 Eina_List *drop_list;
379 Dnd_Drop *drop;
380
381 drop_list = efl_key_data_get(obj, "__drop_list");
382 EINA_LIST_FREE(drop_list, drop)
383 {
384 efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_ENTER,
385 _dnd_drag_enter_leave_cb, drop->enter);
386 efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_LEAVE,
387 _dnd_drag_enter_leave_cb, drop->leave);
388 efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_POS,
389 _dnd_drag_pos_cb, drop->pos);
390 efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_DROP,
391 _dnd_drop_cb, drop);
392 free(drop->enter);
393 free(drop->leave);
394 free(drop->pos);
395 free(drop);
396 }
397}
398
399EAPI Eina_Bool
400elm_drop_target_add(Evas_Object *obj, Elm_Sel_Format format,
401 Elm_Drag_State enter_cb, void *enter_data,
402 Elm_Drag_State leave_cb, void *leave_data,
403 Elm_Drag_Pos pos_cb, void *pos_data,
404 Elm_Drop_Cb drop_cb, void *drop_data)
405{
406 Eo *sel_man = _selection_manager_get(obj);
407 int seatid = 1;
408 Dnd_Drag_State *enter, *leave;
409 Dnd_Drag_Pos *pos;
410 Dnd_Drop *drop;
411 Eina_List *drop_list;
412
413 enter = calloc(1, sizeof(Dnd_Drag_State));
414 leave = calloc(1, sizeof(Dnd_Drag_State));
415 pos = calloc(1, sizeof(Dnd_Drag_Pos));
416 drop = calloc(1, sizeof(Dnd_Drop));
417 if (!enter || !leave || !pos || !drop) return EINA_FALSE;
418#ifdef HAVE_ELEMENTARY_WL2
419 seatid = _wl_default_seat_id_get(obj);
420#endif
421 enter->state_cb = enter_cb;
422 enter->state_data = enter_data;
423 leave->state_cb = leave_cb;
424 leave->state_data = leave_data;
425 pos->pos_cb = pos_cb;
426 pos->pos_data = pos_data;
427 drop->obj = obj;
428 drop->format = format;
429 drop->drop_cb = drop_cb;
430 drop->drop_data = drop_data;
431 drop->enter = enter;
432 drop->leave = leave;
433 drop->pos = pos;
434
435 drop_list = efl_key_data_get(obj, "__drop_list");
436 drop_list = eina_list_append(drop_list, drop);
437 efl_key_data_set(obj, "__drop_list", drop_list);
438 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
439 _drop_obj_del_cb, NULL);
440 efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_ENTER,
441 _dnd_drag_enter_leave_cb, enter);
442 efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_LEAVE,
443 _dnd_drag_enter_leave_cb, leave);
444 efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_POS,
445 _dnd_drag_pos_cb, pos);
446 efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_DROP,
447 _dnd_drop_cb, drop);
448 efl_selection_manager_drop_target_add(sel_man, obj, format, seatid);
449
450
451 return EINA_TRUE;
452}
453
454EAPI Eina_Bool
455elm_drop_target_del(Evas_Object *obj, Elm_Sel_Format format,
456 Elm_Drag_State enter_cb, void *enter_data,
457 Elm_Drag_State leave_cb, void *leave_data,
458 Elm_Drag_Pos pos_cb, void *pos_data,
459 Elm_Drop_Cb drop_cb, void *drop_data)
460{
461 Eo *sel_man = _selection_manager_get(obj);
462 int seatid = 1;
463 //Eina_List *l, *l2;
464 Eina_List *drop_list;
465 Dnd_Drop *drop;
466
467#ifdef HAVE_ELEMENTARY_WL2
468 seatid = _wl_default_seat_id_get(obj);
469#endif
470
471 drop_list = efl_key_data_get(obj, "__drop_list");
472 drop = eina_list_data_get(drop_list);
473 if (drop &&
474 (drop->format == drop->format) &&
475 (drop->enter->state_cb == enter_cb) &&
476 (drop->enter->state_data == enter_data) &&
477 (drop->leave->state_cb == leave_cb) &&
478 (drop->leave->state_data == leave_data) &&
479 (drop->pos->pos_cb == pos_cb) &&
480 (drop->pos->pos_data == pos_data) &&
481 (drop->drop_cb == drop_cb) &&
482 (drop->drop_data == drop_data))
483 {
484 drop_list = eina_list_remove(drop_list, drop);
485 efl_key_data_set(obj, "__drop_list", drop_list);
486 evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _drop_obj_del_cb);
487 efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_ENTER,
488 _dnd_drag_enter_leave_cb, drop->enter);
489 efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_LEAVE,
490 _dnd_drag_enter_leave_cb, drop->leave);
491 efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_POS,
492 _dnd_drag_pos_cb, drop->pos);
493 efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_DROP,
494 _dnd_drop_cb, drop);
495 free(drop->enter);
496 free(drop->leave);
497 free(drop->pos);
498 free(drop);
499 }
500 efl_selection_manager_drop_target_del(sel_man, obj, format, seatid);
501
502 return EINA_TRUE;
503}
504
505static Efl_Object *
506_dnd_item_func(void *data, Efl_Canvas_Object *item, Eina_Position2D pos, Eina_Position2D *pos_ret)
507{
508 Elm_Xy_Item_Get_Cb item_get_cb = data;
509 Evas_Coord x, y;
510 Efl_Object *obj = NULL;
511
512 x = y = 0;
513 if (item_get_cb)
514 obj = item_get_cb(item, pos.x, pos.y, &x, &y);
515 if (pos_ret)
516 {
517 pos_ret->x = x;
518 pos_ret->y = y;
519 }
520
521 return obj;
522}
523
524static void
525_dnd_cont_drag_pos_cb(void *data, const Efl_Event *event)
526{
527 Dnd_Cont_Drag_Pos *pos = data;
528 Efl_Dnd_Drag_Pos *ddata = event->info;
529 Evas_Coord xret = 0, yret = 0;
530
531 if (pos->item_get_cb)
532 {
533 Evas_Coord x, y;
534 evas_object_geometry_get(event->object, &x, &y, NULL, NULL);
535 pos->item_get_cb(event->object, ddata->pos.x + x, ddata->pos.y + y,
536 &xret, &yret);
537 }
538 if (pos->pos_cb)
539 pos->pos_cb(pos->pos_data, event->object, ddata->item, ddata->pos.x, ddata->pos.y,
540 xret, yret, ddata->action);
541}
542
543static void
544_dnd_cont_drop_cb(void *data, const Efl_Event *event)
545{
546 Dnd_Cont_Drop *drop = data;
547 Efl_Selection_Data *org_ddata = event->info;
548 Elm_Selection_Data ddata;
549 Evas_Coord xret = 0, yret = 0;
550
551 ddata.x = org_ddata->pos.x;
552 ddata.y = org_ddata->pos.y;
553 ddata.format = org_ddata->format;
554 ddata.action = org_ddata->action;
555 ddata.data = calloc(1, org_ddata->data.len);
556 if (!ddata.data) return;
557 ddata.data = memcpy(ddata.data, org_ddata->data.mem, org_ddata->data.len);
558 ddata.len = org_ddata->data.len;
559
560 if (drop->item_get_cb)
561 {
562 Evas_Coord x, y;
563 evas_object_geometry_get(event->object, &x, &y, NULL, NULL);
564 drop->item_get_cb(event->object, ddata.x + x, ddata.y + y,
565 &xret, &yret);
566 }
567
568 if (drop->drop_cb)
569 drop->drop_cb(drop->drop_data, event->object, org_ddata->item,
570 &ddata, xret, yret);
571 free(ddata.data);
572}
573
574static void
575_cont_drop_free_data(Evas_Object *obj)
576{
577 Eina_List *cont_drop_list;
578 Dnd_Cont_Drop *drop;
579
580 cont_drop_list = efl_key_data_get(obj, "__cont_drop_item");
581 drop = eina_list_data_get(cont_drop_list);
582 if (drop)
583 {
584 efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_ENTER,
585 _dnd_drag_enter_leave_cb, drop->enter);
586 efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_LEAVE,
587 _dnd_drag_enter_leave_cb, drop->leave);
588 efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_POS,
589 _dnd_cont_drag_pos_cb, drop->pos);
590 efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_DROP,
591 _dnd_cont_drop_cb, drop);
592 free(drop->enter);
593 free(drop->leave);
594 free(drop->pos);
595 cont_drop_list = eina_list_remove(cont_drop_list, drop);
596 efl_key_data_set(obj, "__cont_drop_item", cont_drop_list);
597 free(drop);
598 }
599}
600
601static void
602_cont_drop_obj_del_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *info EINA_UNUSED)
603{
604 _cont_drop_free_data(obj);
605}
606
607EAPI Eina_Bool
608elm_drop_item_container_add(Evas_Object *obj,
609 Elm_Sel_Format format,
610 Elm_Xy_Item_Get_Cb item_get_cb,
611 Elm_Drag_State enter_cb, void *enter_data,
612 Elm_Drag_State leave_cb, void *leave_data,
613 Elm_Drag_Item_Container_Pos pos_cb, void *pos_data,
614 Elm_Drop_Item_Container_Cb drop_cb, void *drop_data)
615{
616 Eo *sel_man = _selection_manager_get(obj);
617 int seatid = 1;
618 Dnd_Drag_State *enter, *leave;
619 Dnd_Cont_Drag_Pos *pos;
620 Dnd_Cont_Drop *drop;
621 Eina_List *cont_drop_list;
622
623 enter = calloc(1, sizeof(Dnd_Drag_State));
624 leave = calloc(1, sizeof(Dnd_Drag_State));
625 pos = calloc(1, sizeof(Dnd_Cont_Drag_Pos));
626 drop = calloc(1, sizeof(Dnd_Cont_Drop));
627 if (!enter || !leave || !pos || !drop) return EINA_FALSE;
628#ifdef HAVE_ELEMENTARY_WL2
629 seatid = _wl_default_seat_id_get(obj);
630#endif
631
632 enter->state_cb = enter_cb;
633 enter->state_data = enter_data;
634 leave->state_cb = leave_cb;
635 leave->state_data = leave_data;
636 pos->pos_cb = pos_cb;
637 pos->pos_data = pos_data;
638 pos->item_get_cb = item_get_cb;
639 drop->obj = obj;
640 drop->format = format;
641 drop->drop_cb = drop_cb;
642 drop->drop_data = drop_data;
643 drop->enter = enter;
644 drop->leave = leave;
645 drop->pos = pos;
646
647 cont_drop_list = efl_key_data_get(obj, "__cont_drop_item");
648 cont_drop_list = eina_list_append(cont_drop_list, drop);
649 efl_key_data_set(obj, "__cont_drop_item", cont_drop_list);
650 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
651 _cont_drop_obj_del_cb, NULL);
652 efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_ENTER,
653 _dnd_drag_enter_leave_cb, enter);
654 efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_LEAVE,
655 _dnd_drag_enter_leave_cb, leave);
656 efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_POS,
657 _dnd_cont_drag_pos_cb, pos);
658 efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_DROP,
659 _dnd_cont_drop_cb, drop);
660 efl_selection_manager_container_drop_item_add(sel_man, obj, format,
661 item_get_cb, _dnd_item_func, NULL,
662 seatid);
663
664 return EINA_TRUE;
665}
666
667EAPI Eina_Bool
668elm_drop_item_container_del(Evas_Object *obj)
669{
670 Eo *sel_man = _selection_manager_get(obj);
671 int seatid = 1;
672
673#ifdef HAVE_ELEMENTARY_WL2
674 seatid = _wl_default_seat_id_get(obj);
675#endif
676
677 _cont_drop_free_data(obj);
678 evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _cont_drop_obj_del_cb);
679 efl_selection_manager_container_drop_item_del(sel_man, obj, seatid);
680
681 return EINA_TRUE;
682}
683
684static void
685_cont_drag_data_func(void *data, Efl_Object *obj, Efl_Selection_Format *format,
686 Eina_Rw_Slice *drag_data, Efl_Selection_Action *action)
687{
688 Item_Container_Drag_Info *di;
689
690 di = data;
691 if (!di) return;
692 di->data_get_cb(obj, di->it, &di->user_info);
693 if (format) *format = di->user_info.format;
694 if (drag_data)
695 {
696 if (di->user_info.data)
697 {
698 drag_data->mem = (void *)di->user_info.data;
699 drag_data->len = strlen(di->user_info.data);
700 }
701 }
702 if (action) *action = di->user_info.action;
703}
704
705static Eina_List *
706_cont_drag_icon_list_create(void *data, Efl_Object *obj EINA_UNUSED)
707{
708 Item_Container_Drag_Info *di;
709
710 di = data;
711 return di->user_info.icons;
712}
713
714static Efl_Object *
715_cont_drag_icon_create(void *data, Efl_Object *win, Efl_Object *drag_obj EINA_UNUSED, Eina_Position2D *pos_ret)
716{
717 Item_Container_Drag_Info *di;
718 Elm_Object_Item *it = NULL;
719
720 di = data;
721 if (!di) return NULL;
722 it = di->user_info.createicon(di->user_info.createdata, win, &pos_ret->x, &pos_ret->y);
723 di->it = it;
724 return it;
725}
726
727static Efl_Object *
728_cont_drag_item_func(void *data, Efl_Canvas_Object *item, Eina_Position2D pos, Eina_Position2D *pos_ret)
729{
730 Item_Container_Drag_Info *di = data;
731 Evas_Coord x, y;
732 Efl_Object *obj = NULL;
733
734 x = y = 0;
735 if (di->item_get_cb)
736 obj = di->item_get_cb(item, pos.x, pos.y, &x, &y);
737 if (pos_ret)
738 {
739 pos_ret->x = x;
740 pos_ret->y = y;
741 }
742 di->it = obj;
743
744 return obj;
745}
746
747static void
748_cont_drag_free_data(Evas_Object *obj)
749{
750 Eina_List *di_list;
751 Item_Container_Drag_Info *di;
752
753 di_list = efl_key_data_get(obj, "__cont_drag_item");
754 di = eina_list_data_get(di_list);
755 di_list = eina_list_remove(di_list, di);
756 efl_key_data_set(obj, "__cont_drag_item", di_list);
757 free(di);
758}
759
760static void
761_cont_drag_obj_del_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event EINA_UNUSED)
762{
763 _cont_drag_free_data(obj);
764}
765
766EAPI Eina_Bool
767elm_drag_item_container_add(Evas_Object *obj, double anim_tm, double tm_to_drag,
768 Elm_Xy_Item_Get_Cb item_get_cb, Elm_Item_Container_Data_Get_Cb data_get_cb)
769{
770 Eo *sel_man = _selection_manager_get(obj);
771 int seatid = 1;
772 Eina_List *di_list;
773 Item_Container_Drag_Info *di;
774
775#ifdef HAVE_ELEMENTARY_WL2
776 seatid = _wl_default_seat_id_get(obj);
777#endif
778
779 di = calloc(1, sizeof(Item_Container_Drag_Info));
780 if (!di) return EINA_FALSE;
781 di->data_get_cb = data_get_cb;
782 di->item_get_cb = item_get_cb;
783 di_list = efl_key_data_get(obj, "__cont_drag_item");
784 di_list = eina_list_append(di_list, di);
785 efl_key_data_set(obj, "__cont_drag_item", di_list);
786 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _cont_drag_obj_del_cb, NULL);
787 efl_selection_manager_container_drag_item_add(sel_man, obj, anim_tm, tm_to_drag,
788 di, _cont_drag_data_func, NULL,
789 di, _cont_drag_item_func, NULL,
790 di, _cont_drag_icon_create, NULL,
791 di, _cont_drag_icon_list_create, NULL,
792 seatid);
793 return EINA_TRUE;
794}
795
796EAPI Eina_Bool
797elm_drag_item_container_del(Evas_Object *obj)
798{
799 Eo *sel_man = _selection_manager_get(obj);
800 int seatid = 1;
801
802#ifdef HAVE_ELEMENTARY_WL2
803 seatid = _wl_default_seat_id_get(obj);
804#endif
805
806 _cont_drag_free_data(obj);
807 evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _cont_drag_obj_del_cb);
808 efl_selection_manager_container_drag_item_del(sel_man, obj, seatid);
809
810 return EINA_TRUE;
811}
812
135#include "efl_ui_dnd.eo.c" 813#include "efl_ui_dnd.eo.c"
136#include "efl_ui_dnd_container.eo.c" 814#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 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4#include <Elementary.h>
5#include <Efreet.h>
6#include "elm_priv.h"
7#ifdef HAVE_MMAN_H
8# include <sys/mman.h>
9#endif
10
11//#define DEBUGON 1
12#ifdef DEBUGON
13# define cnp_debug(fmt, args...) fprintf(stderr, __FILE__":%s/%d : " fmt , __FUNCTION__, __LINE__, ##args)
14#else
15# define cnp_debug(x...) do { } while (0)
16#endif
17
18#define ARRAYINIT(foo) [foo] =
19
20EAPI int ELM_CNP_EVENT_SELECTION_CHANGED = -1;
21
22// common stuff
23enum
24{
25 CNP_ATOM_TARGETS = 0,
26 CNP_ATOM_ATOM,
27 CNP_ATOM_LISTING_ATOMS = CNP_ATOM_ATOM,
28 CNP_ATOM_text_urilist,
29 CNP_ATOM_text_x_vcard,
30 CNP_ATOM_image_png,
31 CNP_ATOM_image_jpeg,
32 CNP_ATOM_image_bmp,
33 CNP_ATOM_image_gif,
34 CNP_ATOM_image_tiff,
35 CNP_ATOM_image_svg,
36 CNP_ATOM_image_xpm,
37 CNP_ATOM_image_tga,
38 CNP_ATOM_image_ppm,
39 CNP_ATOM_XELM,
40// CNP_ATOM_text_html_utf8,
41// CNP_ATOM_text_html,
42 CNP_ATOM_UTF8STRING,
43 CNP_ATOM_STRING,
44 CNP_ATOM_COMPOUND_TEXT,
45 CNP_ATOM_TEXT,
46 CNP_ATOM_text_plain_utf8,
47 CNP_ATOM_text_plain,
48
49 CNP_N_ATOMS,
50};
51
52typedef struct _Tmp_Info Tmp_Info;
53typedef struct _Saved_Type Saved_Type;
54typedef struct _Cnp_Escape Cnp_Escape;
55typedef struct _Dropable Dropable;
56typedef struct _Dropable_Cbs Dropable_Cbs;
57static Eina_Bool doaccept = EINA_FALSE;
58
59struct _Tmp_Info
60{
61 char *filename;
62 void *map;
63 int fd;
64 int len;
65};
66
67struct _Saved_Type
68{
69 const char **types;
70 char *imgfile;
71 int ntypes;
72 int x, y;
73 Eina_Bool textreq: 1;
74};
75
76struct _Cnp_Escape
77{
78 const char *escape;
79 const char *value;
80};
81
82struct _Dropable_Cbs
83{
84 EINA_INLIST;
85 Elm_Sel_Format types;
86 Elm_Drag_State entercb;
87 Elm_Drag_State leavecb;
88 Elm_Drag_Pos poscb;
89 Elm_Drop_Cb dropcb;
90 void *enterdata;
91 void *leavedata;
92 void *posdata;
93 void *dropdata;
94};
95
96struct _Dropable
97{
98 Evas_Object *obj;
99 /* FIXME: Cache window */
100 Eina_Inlist *cbs_list; /* List of Dropable_Cbs * */
101 struct {
102 Evas_Coord x, y;
103 Eina_Bool in : 1;
104 const char *type;
105 Elm_Sel_Format format;
106 } last;
107};
108
109struct _Item_Container_Drop_Info
110{ /* Info kept for containers to support drop */
111 Evas_Object *obj;
112 Elm_Xy_Item_Get_Cb itemgetcb;
113 Elm_Drop_Item_Container_Cb dropcb;
114 Elm_Drag_Item_Container_Pos poscb;
115};
116typedef struct _Item_Container_Drop_Info Item_Container_Drop_Info;
117
118struct _Anim_Icon
119{
120 int start_x;
121 int start_y;
122 int start_w;
123 int start_h;
124 Evas_Object *o;
125};
126typedef struct _Anim_Icon Anim_Icon;
127
128struct _Item_Container_Drag_Info
129{ /* Info kept for containers to support drag */
130 Evas_Object *obj;
131 Ecore_Timer *tm; /* When this expires, start drag */
132 double anim_tm; /* Time period to set tm */
133 double tm_to_drag; /* Time period to set tm */
134 Elm_Xy_Item_Get_Cb itemgetcb;
135 Elm_Item_Container_Data_Get_Cb data_get;
136
137 Evas_Coord x_down; /* Mouse down x cord when drag starts */
138 Evas_Coord y_down; /* Mouse down y cord when drag starts */
139
140 /* Some extra information needed to impl default anim */
141 Evas *e;
142 Eina_List *icons; /* List of icons to animate (Anim_Icon) */
143 int final_icon_w; /* We need the w and h of the final icon for the animation */
144 int final_icon_h;
145 Ecore_Animator *ea;
146
147 Elm_Drag_User_Info user_info;
148};
149typedef struct _Item_Container_Drag_Info Item_Container_Drag_Info;
150
151typedef struct _Cnp_Atom Cnp_Atom;
152
153static int _elm_cnp_init_count = 0;
154/* Stringshared, so I can just compare pointers later */
155static const char *text_uri;
156
157/* Hash table type->Elm_Sel_Format */
158static Eina_Hash *_types_hash = NULL;
159
160/* Data for DND in progress */
161static Saved_Type savedtypes = { NULL, NULL, 0, 0, 0, EINA_FALSE };
162
163/* Drag & Drop functions */
164/* FIXME: Way too many globals */
165static Eina_List *drops = NULL;
166static Evas_Object *dragwin = NULL;
167static int dragwin_x_start, dragwin_y_start;
168static int dragwin_x_end, dragwin_y_end;
169static int _dragx = 0, _dragy = 0;
170static Ecore_Event_Handler *handler_pos = NULL;
171static Ecore_Event_Handler *handler_drop = NULL;
172static Ecore_Event_Handler *handler_enter = NULL;
173static Ecore_Event_Handler *handler_leave = NULL;
174#ifdef HAVE_ELEMENTARY_X
175static Ecore_Event_Handler *handler_status = NULL;
176static Ecore_Event_Handler *handler_up = NULL;
177#endif
178
179/* TODO BUG: should NEVER have these as globals! They should be per context (window). */
180static Elm_Drag_Pos dragposcb = NULL;
181static Elm_Drag_Accept dragacceptcb = NULL;
182static Elm_Drag_State dragdonecb = NULL;
183static void *dragposdata = NULL;
184static void *dragacceptdata = NULL;
185static void *dragdonedata = NULL;
186static Evas_Object *dragwidget = NULL;
187static Elm_Xdnd_Action dragaction = ELM_XDND_ACTION_UNKNOWN;
188
189static Eina_List *cont_drop_tg = NULL; /* List of Item_Container_Drop_Info */
190static Eina_List *cont_drag_tg = NULL; /* List of Item_Container_Drag_Info */
191
192static void _cont_obj_mouse_up( void *data, Evas *e, Evas_Object *obj, void *event_info);
193static void _cont_obj_mouse_move( void *data, Evas *e, Evas_Object *obj, void *event_info);
194static void _all_drop_targets_cbs_del(void *data, Evas *e, Evas_Object *obj, void *info);
195static Eina_Bool _elm_cnp_shutdown(void);
196static Eina_Bool _local_elm_drop_target_del(Evas_Object *obj, Elm_Sel_Format format,
197 Elm_Drag_State entercb, void *enterdata,
198 Elm_Drag_State leavecb, void *leavedata,
199 Elm_Drag_Pos poscb, void *posdata,
200 Elm_Drop_Cb dropcb, void *dropdata);
201
202static Tmp_Info *_tempfile_new (int size);
203static int _tmpinfo_free (Tmp_Info *tmp);
204
205static 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);
206static Eina_Bool _local_elm_object_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type selection);
207static Eina_Bool _local_elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, const void *selbuf, size_t buflen);
208#ifdef HAVE_ELEMENTARY_X
209static Ecore_X_Window _x11_elm_widget_xwin_get(const Evas_Object *obj);
210
211typedef struct _X11_Cnp_Selection X11_Cnp_Selection;
212
213typedef Eina_Bool (*X11_Converter_Fn_Cb) (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
214typedef int (*X11_Response_Handler_Cb) (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *);
215typedef Eina_Bool (*X11_Data_Preparer_Cb) (Ecore_X_Event_Selection_Notify *, Elm_Selection_Data *, Tmp_Info **);
216
217static void _x11_sel_obj_del (void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED);
218static void _x11_sel_obj_del2 (void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED);
219static Eina_Bool _x11_selection_clear (void *udata EINA_UNUSED, int type, void *event);
220static Eina_Bool _x11_selection_notify (void *udata EINA_UNUSED, int type, void *event);
221static Eina_Bool _x11_targets_converter (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
222static Eina_Bool _x11_text_converter (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
223static Eina_Bool _x11_general_converter (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
224static Eina_Bool _x11_image_converter (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
225static Eina_Bool _x11_vcard_send (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
226static Eina_Bool _x11_is_uri_type_data (X11_Cnp_Selection *sel EINA_UNUSED, Ecore_X_Event_Selection_Notify *notify);
227static Eina_Bool _x11_notify_handler_targets (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify);
228static Eina_Bool _x11_data_preparer_text (Ecore_X_Event_Selection_Notify *notify, Elm_Selection_Data *ddata, Tmp_Info **tmp_info);
229static Eina_Bool _x11_data_preparer_markup (Ecore_X_Event_Selection_Notify *notify, Elm_Selection_Data *ddata, Tmp_Info **tmp_info);
230static Eina_Bool _x11_data_preparer_image (Ecore_X_Event_Selection_Notify *notify, Elm_Selection_Data *ddata, Tmp_Info **tmp_info);
231static Eina_Bool _x11_data_preparer_uri (Ecore_X_Event_Selection_Notify *notify, Elm_Selection_Data *ddata, Tmp_Info **tmp_info);
232//static int _x11_notify_handler_html (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify);
233static Eina_Bool _x11_data_preparer_vcard (Ecore_X_Event_Selection_Notify *notify, Elm_Selection_Data *ddata, Tmp_Info **tmp_info);
234static Eina_Bool _x11_dnd_enter (void *data EINA_UNUSED, int etype EINA_UNUSED, void *ev);
235static Eina_Bool _x11_dnd_drop (void *data EINA_UNUSED, int etype EINA_UNUSED, void *ev);
236static Eina_Bool _x11_dnd_position (void *data EINA_UNUSED, int etype EINA_UNUSED, void *ev);
237static Eina_Bool _x11_dnd_status (void *data EINA_UNUSED, int etype EINA_UNUSED, void *ev);
238static Eina_Bool _x11_dnd_leave (void *data EINA_UNUSED, int etype EINA_UNUSED, void *ev);
239static Eina_Bool _x11_drag_mouse_up (void *data, int etype EINA_UNUSED, void *event);
240static void _x11_drag_move (void *data EINA_UNUSED, Ecore_X_Xdnd_Position *pos);
241
242static Eina_Bool _x11_elm_cnp_init (void);
243static 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);
244static 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);
245static Eina_Bool _x11_elm_object_cnp_selection_clear (Evas_Object *obj, Elm_Sel_Type selection);
246static 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);
247static Eina_Bool _x11_elm_drop_target_add (Evas_Object *obj, Elm_Sel_Format format,
248 Elm_Drag_State entercb, void *enterdata,
249 Elm_Drag_State leavecb, void *leavedata,
250 Elm_Drag_Pos poscb, void *posdata,
251 Elm_Drop_Cb dropcb, void *dropdata);
252static Eina_Bool _x11_elm_drop_target_del (Evas_Object *obj, Elm_Sel_Format format,
253 Elm_Drag_State entercb, void *enterdata,
254 Elm_Drag_State leavecb, void *leavedata,
255 Elm_Drag_Pos poscb, void *posdata,
256 Elm_Drop_Cb dropcb, void *dropdata);
257static Eina_Bool _x11_elm_selection_selection_has_owner (Evas_Object *obj EINA_UNUSED);
258
259#endif
260
261#ifdef HAVE_ELEMENTARY_WL2
262typedef struct _Wl_Cnp_Selection Wl_Cnp_Selection;
263
264typedef Eina_Bool (*Wl_Converter_Fn_Cb) (char *target, Wl_Cnp_Selection *sel, void *data, int size, void **data_ret, int *size_ret);
265static Eina_Bool _wl_targets_converter(char *target, Wl_Cnp_Selection *sel, void *data, int size, void **data_ret, int *size_ret);
266static Eina_Bool _wl_general_converter(char *target, Wl_Cnp_Selection *sel, void *data, int size, void **data_ret, int *size_ret);
267static Eina_Bool _wl_text_converter(char *target, Wl_Cnp_Selection *sel, void *data, int size, void **data_ret, int *size_ret);
268
269typedef 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);
270static 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);
271static 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);
272static 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);
273static 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);
274static 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);
275#endif
276
277struct _Cnp_Atom
278{
279 const char *name;
280 Elm_Sel_Format formats;
281#ifdef HAVE_ELEMENTARY_X
282 /* Called by ecore to do conversion */
283 X11_Converter_Fn_Cb x_converter;
284 X11_Data_Preparer_Cb x_data_preparer;
285 /* Atom */
286 Ecore_X_Atom x_atom;
287#endif
288#ifdef HAVE_ELEMENTARY_WL2
289 Wl_Converter_Fn_Cb wl_converter;
290 Wl_Data_Preparer_Cb wl_data_preparer;
291#endif
292
293 void *_term;
294};
295
296static Eina_List *
297_dropable_list_geom_find(Evas *evas, Evas_Coord px, Evas_Coord py)
298{
299 Eina_List *itr, *top_objects_list = NULL, *dropable_list = NULL;
300 Evas_Object *top_obj;
301 Dropable *dropable = NULL;
302
303 if (!drops) return NULL;
304
305 /* We retrieve the (non-smart) objects pointed by (px, py) */
306 top_objects_list = evas_tree_objects_at_xy_get(evas, NULL, px, py);
307 /* We walk on this list from the last because if the list contains more than one
308 * element, all but the last will repeat events. The last one can repeat events
309 * or not. Anyway, this last one is the first that has to be taken into account
310 * for the determination of the drop target.
311 */
312 EINA_LIST_REVERSE_FOREACH(top_objects_list, itr, top_obj)
313 {
314 Evas_Object *object = top_obj;
315 /* We search for the dropable data into the object. If not found, we search into its parent.
316 * For example, if a button is a drop target, the first object will be an (internal) image.
317 * The drop target is attached to the button, i.e to image's parent. That's why we need to
318 * walk on the parents until NULL.
319 * If we find this dropable data, we found our drop target.
320 */
321 while (object)
322 {
323 dropable = efl_key_data_get(object, "__elm_dropable");
324 if (dropable)
325 {
326 Eina_Bool exist = EINA_FALSE;
327 Eina_List *l;
328 Dropable *d = NULL;
329 EINA_LIST_FOREACH(dropable_list, l, d)
330 {
331 if (d == dropable)
332 {
333 exist = EINA_TRUE;
334 break;
335 }
336 }
337 if (!exist)
338 dropable_list = eina_list_append(dropable_list, dropable);
339 object = evas_object_smart_parent_get(object);
340 if (dropable)
341 cnp_debug("Drop target %p of type %s found\n",
342 dropable->obj, efl_class_name_get(efl_class_get(dropable->obj)));
343 }
344 else
345 object = evas_object_smart_parent_get(object);
346 }
347 }
348 eina_list_free(top_objects_list);
349 return dropable_list;
350}
351
352static void
353_dropable_coords_adjust(Dropable *dropable, Evas_Coord *x, Evas_Coord *y)
354{
355 Ecore_Evas *ee;
356 Evas *evas = evas_object_evas_get(dropable->obj);
357 int ex = 0, ey = 0, ew = 0, eh = 0;
358 Evas_Object *win;
359
360 ee = ecore_evas_ecore_evas_get(evas);
361 ecore_evas_geometry_get(ee, &ex, &ey, &ew, &eh);
362 *x = *x - ex;
363 *y = *y - ey;
364
365 /* For Wayland, frame coords have to be subtracted. */
366 Evas_Coord fx, fy;
367 evas_output_framespace_get(evas, &fx, &fy, NULL, NULL);
368 if (fx || fy) cnp_debug("evas frame fx %d fy %d\n", fx, fy);
369 *x = *x - fx;
370 *y = *y - fy;
371
372 if (elm_widget_is(dropable->obj))
373 {
374 win = elm_widget_top_get(dropable->obj);
375 if (win && efl_isa(win, EFL_UI_WIN_CLASS))
376 {
377 Evas_Coord x2, y2;
378 int rot = elm_win_rotation_get(win);
379 switch (rot)
380 {
381 case 90:
382 x2 = ew - *y;
383 y2 = *x;
384 break;
385 case 180:
386 x2 = ew - *x;
387 y2 = eh - *y;
388 break;
389 case 270:
390 x2 = *y;
391 y2 = eh - *x;
392 break;
393 default:
394 x2 = *x;
395 y2 = *y;
396 break;
397 }
398 cnp_debug("rotation %d, w %d, h %d - x:%d->%d, y:%d->%d\n",
399 rot, ew, eh, *x, x2, *y, y2);
400 *x = x2;
401 *y = y2;
402 }
403 }
404}
405
406static Elm_Sel_Format
407_dnd_types_to_format(const char **types, int ntypes)
408{
409 Elm_Sel_Format ret_type = 0;
410 int i;
411 for (i = 0; i < ntypes; i++)
412 {
413 Cnp_Atom *atom = eina_hash_find(_types_hash, types[i]);
414 if (atom) ret_type |= atom->formats;
415 }
416 return ret_type;
417}
418
419static Eina_Bool
420_drag_cancel_animate(void *data, double pos)
421{ /* Animation to "move back" drag-window */
422 if (pos >= 0.99)
423 {
424#ifdef HAVE_ELEMENTARY_X
425 Ecore_X_Window xdragwin = _x11_elm_widget_xwin_get(data);
426 ecore_x_window_ignore_set(xdragwin, 0);
427#endif
428 evas_object_del(data);
429 return ECORE_CALLBACK_CANCEL;
430 }
431 else
432 {
433 int x, y;
434 x = dragwin_x_end - (pos * (dragwin_x_end - dragwin_x_start));
435 y = dragwin_y_end - (pos * (dragwin_y_end - dragwin_y_start));
436 evas_object_move(data, x, y);
437 }
438
439 return ECORE_CALLBACK_RENEW;
440}
441
442static void
443_all_drop_targets_cbs_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *info EINA_UNUSED)
444{
445 Dropable *dropable = NULL;
446 dropable = efl_key_data_get(obj, "__elm_dropable");
447 if (dropable)
448 {
449 Dropable_Cbs *cbs;
450 while (dropable->cbs_list)
451 {
452 cbs = EINA_INLIST_CONTAINER_GET(dropable->cbs_list, Dropable_Cbs);
453 elm_drop_target_del(obj, cbs->types,
454 cbs->entercb, cbs->enterdata, cbs->leavecb, cbs->leavedata,
455 cbs->poscb, cbs->posdata, cbs->dropcb, cbs->dropdata);
456 // If elm_drop_target_del() happened to delete dropabale, then
457 // re-fetch it each loop to make sure it didn't
458 dropable = efl_key_data_get(obj, "__elm_dropable");
459 if (!dropable) break;
460 }
461 }
462}
463
464static Cnp_Atom _atoms[CNP_N_ATOMS] = {
465 ARRAYINIT(CNP_ATOM_TARGETS) {
466 .name = "TARGETS",
467 .formats = ELM_SEL_FORMAT_TARGETS,
468#ifdef HAVE_ELEMENTARY_X
469 .x_converter = _x11_targets_converter,
470
471#endif
472#ifdef HAVE_ELEMENTARY_WL2
473 .wl_converter = _wl_targets_converter,
474#endif
475 },
476 ARRAYINIT(CNP_ATOM_ATOM) {
477 .name = "ATOM", // for opera browser
478 .formats = ELM_SEL_FORMAT_TARGETS,
479#ifdef HAVE_ELEMENTARY_X
480 .x_converter = _x11_targets_converter,
481#endif
482#ifdef HAVE_ELEMENTARY_WL2
483 .wl_converter = _wl_targets_converter,
484#endif
485 },
486 ARRAYINIT(CNP_ATOM_XELM) {
487 .name = "application/x-elementary-markup",
488 .formats = ELM_SEL_FORMAT_MARKUP,
489#ifdef HAVE_ELEMENTARY_X
490 .x_converter = _x11_general_converter,
491 .x_data_preparer = _x11_data_preparer_markup,
492#endif
493#ifdef HAVE_ELEMENTARY_WL2
494 .wl_converter = _wl_general_converter,
495 .wl_data_preparer = _wl_data_preparer_markup,
496#endif
497 },
498 ARRAYINIT(CNP_ATOM_text_urilist) {
499 .name = "text/uri-list",
500 .formats = ELM_SEL_FORMAT_IMAGE,
501#ifdef HAVE_ELEMENTARY_X
502 .x_converter = _x11_general_converter,
503 .x_data_preparer = _x11_data_preparer_uri,
504#endif
505#ifdef HAVE_ELEMENTARY_WL2
506 .wl_converter = _wl_general_converter,
507 .wl_data_preparer = _wl_data_preparer_uri,
508#endif
509 },
510 ARRAYINIT(CNP_ATOM_text_x_vcard) {
511 .name = "text/x-vcard",
512 .formats = ELM_SEL_FORMAT_VCARD,
513#ifdef HAVE_ELEMENTARY_X
514 .x_converter = _x11_vcard_send,
515 .x_data_preparer = _x11_data_preparer_vcard,
516#endif
517#ifdef HAVE_ELEMENTARY_WL2
518 .wl_data_preparer = _wl_data_preparer_vcard,
519#endif
520 },
521 ARRAYINIT(CNP_ATOM_image_png) {
522 .name = "image/png",
523 .formats = ELM_SEL_FORMAT_IMAGE,
524#ifdef HAVE_ELEMENTARY_X
525 .x_converter = _x11_image_converter,
526 .x_data_preparer = _x11_data_preparer_image,
527#endif
528#ifdef HAVE_ELEMENTARY_WL2
529 .wl_data_preparer = _wl_data_preparer_image,
530#endif
531 },
532 ARRAYINIT(CNP_ATOM_image_jpeg) {
533 .name = "image/jpeg",
534 .formats = ELM_SEL_FORMAT_IMAGE,
535#ifdef HAVE_ELEMENTARY_X
536 .x_converter = _x11_image_converter,
537 .x_data_preparer = _x11_data_preparer_image,
538#endif
539#ifdef HAVE_ELEMENTARY_WL2
540 .wl_data_preparer = _wl_data_preparer_image,
541#endif
542 },
543 ARRAYINIT(CNP_ATOM_image_bmp) {
544 .name = "image/x-ms-bmp",
545 .formats = ELM_SEL_FORMAT_IMAGE,
546#ifdef HAVE_ELEMENTARY_X
547 .x_converter = _x11_image_converter,
548 .x_data_preparer = _x11_data_preparer_image,
549#endif
550#ifdef HAVE_ELEMENTARY_WL2
551 .wl_data_preparer = _wl_data_preparer_image,
552#endif
553 },
554 ARRAYINIT(CNP_ATOM_image_gif) {
555 .name = "image/gif",
556 .formats = ELM_SEL_FORMAT_IMAGE,
557#ifdef HAVE_ELEMENTARY_X
558 .x_converter = _x11_image_converter,
559 .x_data_preparer = _x11_data_preparer_image,
560#endif
561#ifdef HAVE_ELEMENTARY_WL2
562 .wl_data_preparer = _wl_data_preparer_image,
563#endif
564 },
565 ARRAYINIT(CNP_ATOM_image_tiff) {
566 .name = "image/tiff",
567 .formats = ELM_SEL_FORMAT_IMAGE,
568#ifdef HAVE_ELEMENTARY_X
569 .x_converter = _x11_image_converter,
570 .x_data_preparer = _x11_data_preparer_image,
571#endif
572#ifdef HAVE_ELEMENTARY_WL2
573 .wl_data_preparer = _wl_data_preparer_image,
574#endif
575 },
576 ARRAYINIT(CNP_ATOM_image_svg) {
577 .name = "image/svg+xml",
578 .formats = ELM_SEL_FORMAT_IMAGE,
579#ifdef HAVE_ELEMENTARY_X
580 .x_converter = _x11_image_converter,
581 .x_data_preparer = _x11_data_preparer_image,
582#endif
583#ifdef HAVE_ELEMENTARY_WL2
584 .wl_data_preparer = _wl_data_preparer_image,
585#endif
586 },
587 ARRAYINIT(CNP_ATOM_image_xpm) {
588 .name = "image/x-xpixmap",
589 .formats = ELM_SEL_FORMAT_IMAGE,
590#ifdef HAVE_ELEMENTARY_X
591 .x_converter = _x11_image_converter,
592 .x_data_preparer = _x11_data_preparer_image,
593#endif
594#ifdef HAVE_ELEMENTARY_WL2
595 .wl_data_preparer = _wl_data_preparer_image,
596#endif
597 },
598 ARRAYINIT(CNP_ATOM_image_tga) {
599 .name = "image/x-tga",
600 .formats = ELM_SEL_FORMAT_IMAGE,
601#ifdef HAVE_ELEMENTARY_X
602 .x_converter = _x11_image_converter,
603 .x_data_preparer = _x11_data_preparer_image,
604#endif
605#ifdef HAVE_ELEMENTARY_WL2
606 .wl_data_preparer = _wl_data_preparer_image,
607#endif
608 },
609 ARRAYINIT(CNP_ATOM_image_ppm) {
610 .name = "image/x-portable-pixmap",
611 .formats = ELM_SEL_FORMAT_IMAGE,
612#ifdef HAVE_ELEMENTARY_X
613 .x_converter = _x11_image_converter,
614 .x_data_preparer = _x11_data_preparer_image,
615#endif
616#ifdef HAVE_ELEMENTARY_WL2
617 .wl_data_preparer = _wl_data_preparer_image,
618#endif
619 },
620/*
621 ARRAYINIT(CNP_ATOM_text_html_utf8) {
622 .name = "text/html;charset=utf-8",
623 .formats = ELM_SEL_FORMAT_HTML,
624#ifdef HAVE_ELEMENTARY_X
625 .x_converter = _x11_general_converter,
626 .x_notify = _x11_notify_handler_html,
627#endif
628#ifdef HAVE_ELEMENTARY_WL2
629 .wl_converter = _wl_general_converter,
630 .wl_data_preparer = _wl_data_preparer_handler_html,
631#endif
632
633 },
634 ARRAYINIT(CNP_ATOM_text_html) {
635 .name = "text/html",
636 .formats = ELM_SEL_FORMAT_HTML,
637#ifdef HAVE_ELEMENTARY_X
638 .x_converter = _x11_general_converter,
639 .x_notify = _x11_notify_handler_html,
640#endif
641#ifdef HAVE_ELEMENTARY_WL2
642 .wl_converter = _wl_general_converter,
643 .wl_data_preparer = _wl_data_preparer_handler_html,
644#endif
645 },
646 */
647 ARRAYINIT(CNP_ATOM_UTF8STRING) {
648 .name = "UTF8_STRING",
649 .formats = ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
650#ifdef HAVE_ELEMENTARY_X
651 .x_converter = _x11_text_converter,
652 .x_data_preparer = _x11_data_preparer_text,
653#endif
654#ifdef HAVE_ELEMENTARY_WL2
655 .wl_converter = _wl_text_converter,
656 .wl_data_preparer = _wl_data_preparer_text,
657#endif
658 },
659 ARRAYINIT(CNP_ATOM_STRING) {
660 .name = "STRING",
661 .formats = ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
662#ifdef HAVE_ELEMENTARY_X
663 .x_converter = _x11_text_converter,
664 .x_data_preparer = _x11_data_preparer_text,
665#endif
666#ifdef HAVE_ELEMENTARY_WL2
667 .wl_converter = _wl_text_converter,
668 .wl_data_preparer = _wl_data_preparer_text,
669#endif
670 },
671 ARRAYINIT(CNP_ATOM_COMPOUND_TEXT) {
672 .name = "COMPOUND_TEXT",
673 .formats = ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
674#ifdef HAVE_ELEMENTARY_X
675 .x_converter = _x11_text_converter,
676 .x_data_preparer = _x11_data_preparer_text,
677#endif
678#ifdef HAVE_ELEMENTARY_WL2
679 .wl_converter = _wl_text_converter,
680 .wl_data_preparer = _wl_data_preparer_text,
681#endif
682 },
683 ARRAYINIT(CNP_ATOM_TEXT) {
684 .name = "TEXT",
685 .formats = ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
686#ifdef HAVE_ELEMENTARY_X
687 .x_converter = _x11_text_converter,
688 .x_data_preparer = _x11_data_preparer_text,
689#endif
690#ifdef HAVE_ELEMENTARY_WL2
691 .wl_converter = _wl_text_converter,
692 .wl_data_preparer = _wl_data_preparer_text,
693#endif
694 },
695 ARRAYINIT(CNP_ATOM_text_plain_utf8) {
696 .name = "text/plain;charset=utf-8",
697 .formats = ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
698#ifdef HAVE_ELEMENTARY_X
699 .x_converter = _x11_text_converter,
700 .x_data_preparer = _x11_data_preparer_text,
701#endif
702#ifdef HAVE_ELEMENTARY_WL2
703 .wl_converter = _wl_text_converter,
704 .wl_data_preparer = _wl_data_preparer_text,
705#endif
706 },
707 ARRAYINIT(CNP_ATOM_text_plain) {
708 .name = "text/plain",
709 .formats = ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
710#ifdef HAVE_ELEMENTARY_X
711 .x_converter = _x11_text_converter,
712 .x_data_preparer = _x11_data_preparer_text,
713#endif
714#ifdef HAVE_ELEMENTARY_WL2
715 .wl_converter = _wl_text_converter,
716 .wl_data_preparer = _wl_data_preparer_text,
717#endif
718 },
719};
720
721// x11 specific stuff
722////////////////////////////////////////////////////////////////////////////
723#ifdef HAVE_ELEMENTARY_X
724#define ARRAYINIT(foo) [foo] =
725struct _X11_Cnp_Selection
726{
727 const char *debug;
728 Evas_Object *widget;
729 char *selbuf;
730 Evas_Object *requestwidget;
731 void *udata;
732 Elm_Sel_Format requestformat;
733 Elm_Drop_Cb datacb;
734 Eina_Bool (*set) (Ecore_X_Window, const void *data, int size);
735 Eina_Bool (*clear) (void);
736 void (*request) (Ecore_X_Window, const char *target);
737 Elm_Selection_Loss_Cb loss_cb;
738 void *loss_data;
739
740 Elm_Sel_Format format;
741 Ecore_X_Selection ecore_sel;
742 Ecore_X_Window xwin;
743 Elm_Xdnd_Action action;
744
745 Eina_Bool active : 1;
746};
747
748static X11_Cnp_Selection _x11_selections[ELM_SEL_TYPE_CLIPBOARD + 1] = {
749 ARRAYINIT(ELM_SEL_TYPE_PRIMARY) {
750 .debug = "Primary",
751 .ecore_sel = ECORE_X_SELECTION_PRIMARY,
752 .set = ecore_x_selection_primary_set,
753 .clear = ecore_x_selection_primary_clear,
754 .request = ecore_x_selection_primary_request,
755 },
756 ARRAYINIT(ELM_SEL_TYPE_SECONDARY) {
757 .debug = "Secondary",
758 .ecore_sel = ECORE_X_SELECTION_SECONDARY,
759 .set = ecore_x_selection_secondary_set,
760 .clear = ecore_x_selection_secondary_clear,
761 .request = ecore_x_selection_secondary_request,
762 },
763 ARRAYINIT(ELM_SEL_TYPE_XDND) {
764 .debug = "XDnD",
765 .ecore_sel = ECORE_X_SELECTION_XDND,
766 .request = ecore_x_selection_xdnd_request,
767 },
768 ARRAYINIT(ELM_SEL_TYPE_CLIPBOARD) {
769 .debug = "Clipboard",
770 .ecore_sel = ECORE_X_SELECTION_CLIPBOARD,
771 .set = ecore_x_selection_clipboard_set,
772 .clear = ecore_x_selection_clipboard_clear,
773 .request = ecore_x_selection_clipboard_request,
774 },
775};
776
777static void
778_x11_sel_obj_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
779{
780 X11_Cnp_Selection *sel = data;
781 if (sel->widget == obj)
782 {
783 sel->loss_cb = NULL;
784 sel->loss_data = NULL;
785 sel->widget = NULL;
786 }
787 if (dragwidget == obj) dragwidget = NULL;
788}
789
790static void
791_x11_sel_obj_del2(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
792{
793 X11_Cnp_Selection *sel = data;
794 if (sel->requestwidget == obj) sel->requestwidget = NULL;
795}
796
797static Eina_Bool
798_x11_selection_clear(void *udata EINA_UNUSED, int type EINA_UNUSED, void *event)
799{
800 Ecore_X_Event_Selection_Clear *ev = event;
801 X11_Cnp_Selection *sel;
802 unsigned int i;
803
804 _x11_elm_cnp_init();
805 for (i = ELM_SEL_TYPE_PRIMARY; i <= ELM_SEL_TYPE_CLIPBOARD; i++)
806 {
807 if (_x11_selections[i].ecore_sel == ev->selection) break;
808 }
809 cnp_debug("selection %d clear\n", i);
810 /* Not me... Don't care */
811 if (i > ELM_SEL_TYPE_CLIPBOARD) return ECORE_CALLBACK_PASS_ON;
812
813 sel = _x11_selections + i;
814 if (sel->loss_cb) sel->loss_cb(sel->loss_data, i);
815 if (sel->widget)
816 evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL,
817 _x11_sel_obj_del, sel);
818 if (sel->requestwidget)
819 evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL,
820 _x11_sel_obj_del2, sel);
821 sel->widget = NULL;
822 sel->requestwidget = NULL;
823 sel->loss_cb = NULL;
824 sel->loss_data = NULL;
825
826 sel->active = EINA_FALSE;
827 ELM_SAFE_FREE(sel->selbuf, free);
828 return ECORE_CALLBACK_PASS_ON;
829}
830
831static Eina_Bool
832_x11_fixes_selection_notify(void *d EINA_UNUSED, int t EINA_UNUSED, void *event)
833{
834 Elm_Cnp_Event_Selection_Changed *e;
835 Ecore_X_Event_Fixes_Selection_Notify *ev = event;
836 Elm_Sel_Type type;
837 X11_Cnp_Selection *sel;
838
839 switch (ev->selection)
840 {
841 case ECORE_X_SELECTION_CLIPBOARD:
842 type = ELM_SEL_TYPE_CLIPBOARD;
843 break;
844 case ECORE_X_SELECTION_PRIMARY:
845 type = ELM_SEL_TYPE_PRIMARY;
846 break;
847 default: return ECORE_CALLBACK_RENEW;
848 }
849 sel = _x11_selections + type;
850 if (sel->active && (sel->xwin != ev->owner))
851 _x11_elm_object_cnp_selection_clear(sel->widget, type);
852 e = calloc(1, sizeof(Elm_Cnp_Event_Selection_Changed));
853 EINA_SAFETY_ON_NULL_RETURN_VAL(e, ECORE_CALLBACK_RENEW);
854 e->type = type;
855 e->seat_id = 1; /* under x11 this is always the default seat */
856 e->exists = !!ev->owner;
857 ecore_event_add(ELM_CNP_EVENT_SELECTION_CHANGED, e, NULL, NULL);
858 return ECORE_CALLBACK_RENEW;
859}
860
861/*
862 * Response to a selection notify:
863 * - So we have asked for the selection list.
864 * - If it's the targets list, parse it, and fire of what we want,
865 * else it's the data we want.
866 */
867static Eina_Bool
868_x11_selection_notify(void *udata EINA_UNUSED, int type EINA_UNUSED, void *event)
869{
870 Ecore_X_Event_Selection_Notify *ev = event;
871 X11_Cnp_Selection *sel;
872 int i;
873
874 cnp_debug("selection notify callback: %d\n",ev->selection);
875 switch (ev->selection)
876 {
877 case ECORE_X_SELECTION_PRIMARY:
878 sel = _x11_selections + ELM_SEL_TYPE_PRIMARY;
879 break;
880 case ECORE_X_SELECTION_SECONDARY:
881 sel = _x11_selections + ELM_SEL_TYPE_SECONDARY;
882 break;
883 case ECORE_X_SELECTION_XDND:
884 sel = _x11_selections + ELM_SEL_TYPE_XDND;
885 break;
886 case ECORE_X_SELECTION_CLIPBOARD:
887 sel = _x11_selections + ELM_SEL_TYPE_CLIPBOARD;
888 break;
889 default:
890 return ECORE_CALLBACK_PASS_ON;
891 }
892 cnp_debug("Target is %s\n", ev->target);
893
894 if (ev->selection != ECORE_X_SELECTION_XDND &&
895 (!strcmp(ev->target, "TARGETS") || !strcmp(ev->target, "ATOMS")))
896 {
897 _x11_notify_handler_targets(sel, ev);
898 return ECORE_CALLBACK_PASS_ON;
899 }
900 for (i = 0; i < CNP_N_ATOMS; i++)
901 {
902 if (!strcmp(ev->target, _atoms[i].name))
903 {
904 if (_atoms[i].x_data_preparer)
905 {
906 Elm_Selection_Data ddata;
907 Tmp_Info *tmp_info = NULL;
908 Eina_Bool success;
909 ddata.data = NULL;
910 cnp_debug("Found something: %s\n", _atoms[i].name);
911 success = _atoms[i].x_data_preparer(ev, &ddata, &tmp_info);
912 if (_atoms[i].formats == ELM_SEL_FORMAT_IMAGE && savedtypes.imgfile) break;
913 if (ev->selection == ECORE_X_SELECTION_XDND)
914 {
915 if (success)
916 {
917 Dropable *dropable;
918 Eina_List *l;
919 cnp_debug("drag & drop\n");
920 EINA_LIST_FOREACH(drops, l, dropable)
921 {
922 if (dropable->obj == sel->requestwidget) break;
923 dropable = NULL;
924 }
925 if (dropable)
926 {
927 Dropable_Cbs *cbs;
928 Eina_Inlist *itr;
929 ddata.x = savedtypes.x;
930 ddata.y = savedtypes.y;
931 EINA_INLIST_FOREACH_SAFE(dropable->cbs_list, itr, cbs)
932 if ((cbs->types & dropable->last.format) && cbs->dropcb)
933 cbs->dropcb(cbs->dropdata, dropable->obj, &ddata);
934 }
935 }
936 /* We have to finish DnD, no matter what */
937 ecore_x_dnd_send_finished();
938 }
939 else if (sel->datacb && success)
940 {
941 ddata.x = ddata.y = 0;
942 sel->datacb(sel->udata, sel->requestwidget, &ddata);
943 }
944 free(ddata.data);
945 if (tmp_info) _tmpinfo_free(tmp_info);
946 }
947 else cnp_debug("Ignored: No handler!\n");
948 break;
949 }
950 }
951 return ECORE_CALLBACK_PASS_ON;
952}
953
954static Elm_Sel_Format
955_get_selection_type(void *data, int size)
956{
957 if (size == sizeof(Elm_Sel_Type))
958 {
959 unsigned int seltype = *((unsigned int *)data);
960 if (seltype > ELM_SEL_TYPE_CLIPBOARD)
961 return ELM_SEL_FORMAT_NONE;
962 X11_Cnp_Selection *sel = _x11_selections + seltype;
963 if (sel->active &&
964 (sel->format >= ELM_SEL_FORMAT_TARGETS) &&
965 (sel->format <= ELM_SEL_FORMAT_HTML))
966 return sel->format;
967 }
968 return ELM_SEL_FORMAT_NONE;
969}
970
971static Eina_Bool
972_x11_targets_converter(char *target EINA_UNUSED, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize)
973{
974 int i, count;
975 Ecore_X_Atom *aret;
976 X11_Cnp_Selection *sel;
977 Elm_Sel_Format seltype;
978
979 if (!data_ret) return EINA_FALSE;
980 if (_get_selection_type(data, size) == ELM_SEL_FORMAT_NONE)
981 {
982 /* TODO : fallback into precise type */
983 seltype = ELM_SEL_FORMAT_TEXT;
984 }
985 else
986 {
987 sel = _x11_selections + *((int *)data);
988 seltype = sel->format;
989 }
990
991 for (i = CNP_ATOM_LISTING_ATOMS + 1, count = 0; i < CNP_N_ATOMS ; i++)
992 {
993 if (seltype & _atoms[i].formats) count++;
994 }
995 aret = malloc(sizeof(Ecore_X_Atom) * count);
996 if (!aret) return EINA_FALSE;
997 for (i = CNP_ATOM_LISTING_ATOMS + 1, count = 0; i < CNP_N_ATOMS ; i++)
998 {
999 if (seltype & _atoms[i].formats)
1000 aret[count ++] = _atoms[i].x_atom;
1001 }
1002
1003 *data_ret = aret;
1004 if (typesize) *typesize = 32 /* urk */;
1005 if (ttype) *ttype = ECORE_X_ATOM_ATOM;
1006 if (size_ret) *size_ret = count;
1007 return EINA_TRUE;
1008}
1009
1010static Eina_Bool
1011_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)
1012{
1013 cnp_debug("Image converter called\n");
1014 return EINA_TRUE;
1015}
1016
1017static Eina_Bool
1018_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)
1019{
1020 X11_Cnp_Selection *sel;
1021
1022 cnp_debug("Vcard send called\n");
1023 sel = _x11_selections + *((int *)data);
1024 if (data_ret) *data_ret = strdup(sel->selbuf);
1025 if (size_ret) *size_ret = strlen(sel->selbuf);
1026 return EINA_TRUE;
1027}
1028
1029static Eina_Bool
1030_x11_is_uri_type_data(X11_Cnp_Selection *sel EINA_UNUSED, Ecore_X_Event_Selection_Notify *notify)
1031{
1032 Ecore_X_Selection_Data *data;
1033 char *p;
1034
1035 data = notify->data;
1036 cnp_debug("data->format is %d %p %p\n", data->format, notify, data);
1037 if (data->content == ECORE_X_SELECTION_CONTENT_FILES) return EINA_TRUE;
1038 p = (char *)data->data;
1039 if (!p) return EINA_TRUE;
1040 cnp_debug("Got %s\n", p);
1041 if (strncmp(p, "file:/", 6))
1042 {
1043 if (*p != '/') return EINA_FALSE;
1044 }
1045 return EINA_TRUE;
1046}
1047
1048/*
1049 * Callback to handle a targets response on a selection request:
1050 * So pick the format we'd like; and then request it.
1051 */
1052static Eina_Bool
1053_x11_notify_handler_targets(X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
1054{
1055 Ecore_X_Selection_Data_Targets *targets;
1056 Ecore_X_Atom *atomlist;
1057 int i, j;
1058
1059 targets = notify->data;
1060 atomlist = (Ecore_X_Atom *)(targets->data.data);
1061 for (j = (CNP_ATOM_LISTING_ATOMS + 1); j < CNP_N_ATOMS; j++)
1062 {
1063 cnp_debug("\t%s %d\n", _atoms[j].name, _atoms[j].x_atom);
1064 if (!(_atoms[j].formats & sel->requestformat)) continue;
1065 for (i = 0; i < targets->data.length; i++)
1066 {
1067 if ((_atoms[j].x_atom == atomlist[i]) && (_atoms[j].x_data_preparer))
1068 {
1069 if (j == CNP_ATOM_text_urilist)
1070 {
1071 if (!_x11_is_uri_type_data(sel, notify)) continue;
1072 }
1073 cnp_debug("Atom %s matches\n", _atoms[j].name);
1074 goto done;
1075 }
1076 }
1077 }
1078 cnp_debug("Couldn't find anything that matches\n");
1079 return ECORE_CALLBACK_PASS_ON;
1080done:
1081 cnp_debug("Sending request for %s, xwin=%#llx\n",
1082 _atoms[j].name, (unsigned long long)sel->xwin);
1083 sel->request(sel->xwin, _atoms[j].name);
1084 return ECORE_CALLBACK_PASS_ON;
1085}
1086
1087static Eina_Bool
1088_x11_data_preparer_text(Ecore_X_Event_Selection_Notify *notify,
1089 Elm_Selection_Data *ddata, Tmp_Info **tmp_info EINA_UNUSED)
1090{
1091 Ecore_X_Selection_Data *data = notify->data;
1092 ddata->format = ELM_SEL_FORMAT_TEXT;
1093 ddata->data = eina_memdup(data->data, data->length, EINA_TRUE);
1094 ddata->len = data->length;
1095 return EINA_TRUE;
1096}
1097
1098static Eina_Bool
1099_x11_data_preparer_markup(Ecore_X_Event_Selection_Notify *notify,
1100 Elm_Selection_Data *ddata, Tmp_Info **tmp_info EINA_UNUSED)
1101{
1102 Ecore_X_Selection_Data *data = notify->data;
1103 ddata->format = ELM_SEL_FORMAT_MARKUP;
1104 ddata->data = eina_memdup(data->data, data->length, EINA_TRUE);
1105 ddata->len = data->length;
1106 return EINA_TRUE;
1107}
1108
1109/**
1110 * So someone is pasting an image into my entry or widget...
1111 */
1112static Eina_Bool
1113_x11_data_preparer_uri(Ecore_X_Event_Selection_Notify *notify,
1114 Elm_Selection_Data *ddata, Tmp_Info **tmp_info EINA_UNUSED)
1115{
1116 Ecore_X_Selection_Data *data;
1117 Ecore_X_Selection_Data_Files *files;
1118 char *p, *stripstr = NULL;
1119
1120 data = notify->data;
1121 cnp_debug("data->format is %d %p %p\n", data->format, notify, data);
1122 if (data->content == ECORE_X_SELECTION_CONTENT_FILES)
1123 {
1124 Efreet_Uri *uri;
1125 Eina_Strbuf *strbuf;
1126 int i;
1127
1128 cnp_debug("got a files list\n");
1129 files = notify->data;
1130 /*
1131 if (files->num_files > 1)
1132 {
1133 // Don't handle many items <- this makes mr bigglesworth sad :(
1134 cnp_debug("more then one file: Bailing\n");
1135 return EINA_FALSE;
1136 }
1137 stripstr = p = strdup(files->files[0]);
1138 */
1139
1140 strbuf = eina_strbuf_new();
1141 if (!strbuf)
1142 return EINA_FALSE;
1143
1144 for (i = 0; i < files->num_files ; i++)
1145 {
1146 uri = efreet_uri_decode(files->files[i]);
1147 if (uri)
1148 {
1149 eina_strbuf_append(strbuf, uri->path);
1150 efreet_uri_free(uri);
1151 }
1152 else
1153 {
1154 eina_strbuf_append(strbuf, files->files[i]);
1155 }
1156 if (i < (files->num_files - 1))
1157 eina_strbuf_append(strbuf, "\n");
1158 }
1159 stripstr = eina_strbuf_string_steal(strbuf);
1160 eina_strbuf_free(strbuf);
1161 }
1162 else
1163 {
1164 Efreet_Uri *uri;
1165
1166 p = (char *)eina_memdup((unsigned char *)data->data, data->length, EINA_TRUE);
1167 if (!p) return EINA_FALSE;
1168 uri = efreet_uri_decode(p);
1169 if (!uri)
1170 {
1171 /* Is there any reason why we care of URI without scheme? */
1172 if (p[0] == '/') stripstr = p;
1173 else free(p);
1174 }
1175 else
1176 {
1177 free(p);
1178 stripstr = strdup(uri->path);
1179 efreet_uri_free(uri);
1180 }
1181 }
1182
1183 if (!stripstr)
1184 {
1185 cnp_debug("Couldn't find a file\n");
1186 return EINA_FALSE;
1187 }
1188 free(savedtypes.imgfile);
1189 if (savedtypes.textreq)
1190 {
1191 savedtypes.textreq = 0;
1192 savedtypes.imgfile = stripstr;
1193 }
1194 else
1195 {
1196 ddata->format = ELM_SEL_FORMAT_IMAGE;
1197 ddata->data = stripstr;
1198 ddata->len = strlen(stripstr);
1199 savedtypes.imgfile = NULL;
1200 }
1201 return EINA_TRUE;
1202}
1203
1204/**
1205 * Just received an vcard, either through cut and paste, or dnd.
1206 */
1207static Eina_Bool
1208_x11_data_preparer_vcard(Ecore_X_Event_Selection_Notify *notify,
1209 Elm_Selection_Data *ddata, Tmp_Info **tmp_info EINA_UNUSED)
1210{
1211 cnp_debug("vcard receive\n");
1212 Ecore_X_Selection_Data *data = notify->data;
1213 ddata->format = ELM_SEL_FORMAT_VCARD;
1214 ddata->data = eina_memdup(data->data, data->length, EINA_TRUE);
1215 ddata->len = data->length;
1216 return EINA_TRUE;
1217}
1218
1219static Eina_Bool
1220_x11_data_preparer_image(Ecore_X_Event_Selection_Notify *notify,
1221 Elm_Selection_Data *ddata, Tmp_Info **tmp_info)
1222{
1223 Ecore_X_Selection_Data *data = notify->data;
1224 cnp_debug("got a image file!\n");
1225 cnp_debug("Size if %d\n", data->length);
1226
1227 ddata->format = ELM_SEL_FORMAT_IMAGE;
1228 data = notify->data;
1229
1230 Tmp_Info *tmp = _tempfile_new(data->length);
1231 if (!tmp) return EINA_FALSE;
1232 memcpy(tmp->map, data->data, data->length);
1233 munmap(tmp->map, data->length);
1234 ddata->data = strdup(tmp->filename);
1235 ddata->len = strlen(tmp->filename);
1236 *tmp_info = tmp;
1237 return EINA_TRUE;
1238}
1239
1240/**
1241 * Warning: Generic text/html can';t handle it sanely.
1242 * Firefox sends ucs2 (i think).
1243 * chrome sends utf8... blerg
1244 */
1245/*
1246static int
1247_x11_notify_handler_html(X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
1248{
1249 Ecore_X_Selection_Data *data;
1250
1251 cnp_debug("Got some HTML: Checking encoding is useful\n");
1252 data = notify->data;
1253 char *stripstr = malloc(data->length + 1);
1254 if (!stripstr) return 0;
1255 strncpy(stripstr, (char *)data->data, data->length);
1256 stripstr[data->length] = '\0';
1257
1258 if (sel->datacb)
1259 {
1260 Elm_Selection_Data ddata;
1261 ddata.x = ddata.y = 0;
1262 ddata.format = ELM_SEL_FORMAT_HTML;
1263 ddata.data = stripstr;
1264 ddata.len = data->length;
1265 ddata.action = ELM_XDND_ACTION_UNKNOWN;
1266 sel->datacb(sel->udata, sel->widget, &ddata);
1267 free(stripstr);
1268 return 0;
1269 }
1270
1271 cnp_debug("String is %s (%d bytes)\n", stripstr, data->length);
1272 // TODO BUG: should never NEVER assume it's an elm_entry!
1273 _elm_entry_entry_paste(sel->requestwidget, stripstr);
1274 free(stripstr);
1275 return 0;
1276}
1277*/
1278
1279static Eina_Bool
1280_x11_text_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize)
1281{
1282 X11_Cnp_Selection *sel;
1283
1284 cnp_debug("text converter\n");
1285 if (_get_selection_type(data, size) == ELM_SEL_FORMAT_NONE)
1286 {
1287 if (data_ret)
1288 {
1289 *data_ret = malloc(size * sizeof(char) + 1);
1290 if (!*data_ret) return EINA_FALSE;
1291 memcpy(*data_ret, data, size);
1292 ((char**)(data_ret))[0][size] = 0;
1293 }
1294 if (size_ret) *size_ret = size;
1295 return EINA_TRUE;
1296 }
1297 sel = _x11_selections + *((int *)data);
1298 if (!sel->active) return EINA_TRUE;
1299
1300 if ((sel->format & ELM_SEL_FORMAT_MARKUP) ||
1301 (sel->format & ELM_SEL_FORMAT_HTML))
1302 {
1303 *data_ret = _elm_util_mkup_to_text(sel->selbuf);
1304 if (size_ret && *data_ret) *size_ret = strlen(*data_ret);
1305 }
1306 else if (sel->format & ELM_SEL_FORMAT_TEXT)
1307 {
1308 ecore_x_selection_converter_text(target, sel->selbuf,
1309 strlen(sel->selbuf),
1310 data_ret, size_ret,
1311 ttype, typesize);
1312 }
1313 else if (sel->format & ELM_SEL_FORMAT_IMAGE)
1314 {
1315 cnp_debug("Image %s\n", evas_object_type_get(sel->widget));
1316 cnp_debug("Elm type: %s\n", elm_object_widget_type_get(sel->widget));
1317 evas_object_image_file_get(elm_photocam_internal_image_get(sel->widget),
1318 (const char **)data_ret, NULL);
1319 if (!*data_ret) *data_ret = strdup("No file");
1320 else *data_ret = strdup(*data_ret);
1321
1322 if (!*data_ret)
1323 {
1324 ERR("Failed to allocate memory!");
1325 *size_ret = 0;
1326 return EINA_FALSE;
1327 }
1328
1329 *size_ret = strlen(*data_ret);
1330 }
1331 return EINA_TRUE;
1332}
1333
1334static Eina_Bool
1335_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)
1336{
1337 if (_get_selection_type(data, size) == ELM_SEL_FORMAT_NONE)
1338 {
1339 if (data_ret)
1340 {
1341 *data_ret = malloc(size * sizeof(char) + 1);
1342 if (!*data_ret) return EINA_FALSE;
1343 memcpy(*data_ret, data, size);
1344 ((char**)(data_ret))[0][size] = 0;
1345 }
1346 if (size_ret) *size_ret = size;
1347 }
1348 else
1349 {
1350 X11_Cnp_Selection *sel = _x11_selections + *((int *)data);
1351 if (sel->selbuf)
1352 {
1353 if (data_ret) *data_ret = strdup(sel->selbuf);
1354 if (size_ret) *size_ret = strlen(sel->selbuf);
1355 }
1356 else
1357 {
1358 if (data_ret) *data_ret = NULL;
1359 if (size_ret) *size_ret = 0;
1360 }
1361 }
1362 return EINA_TRUE;
1363}
1364
1365static Dropable *
1366_x11_dropable_find(Ecore_X_Window win)
1367{
1368 Eina_List *l;
1369 Dropable *dropable;
1370
1371 if (!drops) return NULL;
1372 EINA_LIST_FOREACH(drops, l, dropable)
1373 {
1374 if (_x11_elm_widget_xwin_get(dropable->obj) == win) return dropable;
1375 }
1376 return NULL;
1377}
1378
1379static Evas *
1380_x11_evas_get_from_xwin(Ecore_X_Window win)
1381{
1382 /* Find the Evas connected to the window */
1383 Dropable *dropable = _x11_dropable_find(win);
1384 return dropable ? evas_object_evas_get(dropable->obj) : NULL;
1385}
1386
1387static Eina_Bool
1388_x11_dnd_enter(void *data EINA_UNUSED, int etype EINA_UNUSED, void *ev)
1389{
1390 Ecore_X_Event_Xdnd_Enter *enter = ev;
1391 int i;
1392 Dropable *dropable;
1393
1394 if (!enter) return EINA_TRUE;
1395 dropable = _x11_dropable_find(enter->win);
1396 if (dropable)
1397 {
1398 cnp_debug("Enter %x\n", enter->win);
1399 }
1400 /* Skip it */
1401 cnp_debug("enter types=%p (%d)\n", enter->types, enter->num_types);
1402 if ((!enter->num_types) || (!enter->types)) return EINA_TRUE;
1403
1404 cnp_debug("Types\n");
1405 savedtypes.ntypes = enter->num_types;
1406 free(savedtypes.types);
1407 savedtypes.types = malloc(sizeof(char *) * enter->num_types);
1408 if (!savedtypes.types) return EINA_FALSE;
1409
1410 for (i = 0; i < enter->num_types; i++)
1411 {
1412 savedtypes.types[i] = eina_stringshare_add(enter->types[i]);
1413 cnp_debug("Type is %s %p %p\n", enter->types[i],
1414 savedtypes.types[i], text_uri);
1415 if (savedtypes.types[i] == text_uri)
1416 {
1417 /* Request it, so we know what it is */
1418 cnp_debug("Sending uri request\n");
1419 savedtypes.textreq = 1;
1420 ELM_SAFE_FREE(savedtypes.imgfile, free);
1421 ecore_x_selection_xdnd_request(enter->win, text_uri);
1422 }
1423 }
1424
1425 /* FIXME: Find an object and make it current */
1426 return EINA_TRUE;
1427}
1428
1429static void
1430_x11_dnd_dropable_handle(Dropable *dropable, Evas_Coord x, Evas_Coord y, Elm_Xdnd_Action action)
1431{
1432 Dropable *d, *last_dropable = NULL;
1433 Eina_List *l;
1434 Dropable_Cbs *cbs;
1435 Eina_Inlist *itr;
1436
1437 EINA_LIST_FOREACH(drops, l, d)
1438 {
1439 if (d->last.in)
1440 {
1441 last_dropable = d;
1442 break;
1443 }
1444 }
1445 if (last_dropable)
1446 {
1447 if (last_dropable == dropable) // same
1448 {
1449 Evas_Coord ox, oy;
1450
1451 cnp_debug("same obj dropable %p\n", dropable->obj);
1452 evas_object_geometry_get(dropable->obj, &ox, &oy, NULL, NULL);
1453 EINA_INLIST_FOREACH_SAFE(dropable->cbs_list, itr, cbs)
1454 if ((cbs->types & dropable->last.format) && cbs->poscb)
1455 cbs->poscb(cbs->posdata, dropable->obj, x - ox, y - oy, action);
1456 }
1457 else
1458 {
1459 if (dropable) // leave last obj and enter new one
1460 {
1461 cnp_debug("leave %p\n", last_dropable->obj);
1462 cnp_debug("enter %p\n", dropable->obj);
1463 last_dropable->last.in = EINA_FALSE;
1464 last_dropable->last.type = NULL;
1465 dropable->last.in = EINA_TRUE;
1466 EINA_INLIST_FOREACH_SAFE(dropable->cbs_list, itr, cbs)
1467 if ((cbs->types & dropable->last.format) && cbs->entercb)
1468 cbs->entercb(cbs->enterdata, dropable->obj);
1469 EINA_INLIST_FOREACH_SAFE(last_dropable->cbs_list, itr, cbs)
1470 if ((cbs->types & last_dropable->last.format) && cbs->leavecb)
1471 cbs->leavecb(cbs->leavedata, last_dropable->obj);
1472 }
1473 else // leave last obj
1474 {
1475 cnp_debug("leave %p\n", last_dropable->obj);
1476 last_dropable->last.in = EINA_FALSE;
1477 last_dropable->last.type = NULL;
1478 EINA_INLIST_FOREACH_SAFE(last_dropable->cbs_list, itr, cbs)
1479 if ((cbs->types & last_dropable->last.format) && cbs->leavecb)
1480 cbs->leavecb(cbs->leavedata, last_dropable->obj);
1481 }
1482 }
1483 }
1484 else
1485 {
1486 if (dropable) // enter new obj
1487 {
1488 Evas_Coord ox, oy;
1489
1490 cnp_debug("enter %p\n", dropable->obj);
1491 evas_object_geometry_get(dropable->obj, &ox, &oy, NULL, NULL);
1492 dropable->last.in = EINA_TRUE;
1493 EINA_INLIST_FOREACH_SAFE(dropable->cbs_list, itr, cbs)
1494 {
1495 if (cbs->types & dropable->last.format)
1496 {
1497 if (cbs->entercb)
1498 cbs->entercb(cbs->enterdata, dropable->obj);
1499 if (cbs->poscb)
1500 cbs->poscb(cbs->posdata, dropable->obj,
1501 x - ox, y - oy, action);
1502 }
1503 }
1504 }
1505 else
1506 {
1507 cnp_debug("both dropable & last_dropable are null\n");
1508 }
1509 }
1510}
1511
1512static Elm_Xdnd_Action
1513_x11_dnd_action_map(Ecore_X_Atom action)
1514{
1515 Elm_Xdnd_Action act = ELM_XDND_ACTION_UNKNOWN;
1516
1517 if (action == ECORE_X_ATOM_XDND_ACTION_COPY)
1518 act = ELM_XDND_ACTION_COPY;
1519 else if (action == ECORE_X_ATOM_XDND_ACTION_MOVE)
1520 act = ELM_XDND_ACTION_MOVE;
1521 else if (action == ECORE_X_ATOM_XDND_ACTION_PRIVATE)
1522 act = ELM_XDND_ACTION_PRIVATE;
1523 else if (action == ECORE_X_ATOM_XDND_ACTION_ASK)
1524 act = ELM_XDND_ACTION_ASK;
1525 else if (action == ECORE_X_ATOM_XDND_ACTION_LIST)
1526 act = ELM_XDND_ACTION_LIST;
1527 else if (action == ECORE_X_ATOM_XDND_ACTION_LINK)
1528 act = ELM_XDND_ACTION_LINK;
1529 else if (action == ECORE_X_ATOM_XDND_ACTION_DESCRIPTION)
1530 act = ELM_XDND_ACTION_DESCRIPTION;
1531 return act;
1532}
1533
1534static Ecore_X_Atom
1535_x11_dnd_action_rev_map(Elm_Xdnd_Action action)
1536{
1537 Ecore_X_Atom act = ECORE_X_ATOM_XDND_ACTION_MOVE;
1538
1539 if (action == ELM_XDND_ACTION_COPY)
1540 act = ECORE_X_ATOM_XDND_ACTION_COPY;
1541 else if (action == ELM_XDND_ACTION_MOVE)
1542 act = ECORE_X_ATOM_XDND_ACTION_MOVE;
1543 else if (action == ELM_XDND_ACTION_PRIVATE)
1544 act = ECORE_X_ATOM_XDND_ACTION_PRIVATE;
1545 else if (action == ELM_XDND_ACTION_ASK)
1546 act = ECORE_X_ATOM_XDND_ACTION_ASK;
1547 else if (action == ELM_XDND_ACTION_LIST)
1548 act = ECORE_X_ATOM_XDND_ACTION_LIST;
1549 else if (action == ELM_XDND_ACTION_LINK)
1550 act = ECORE_X_ATOM_XDND_ACTION_LINK;
1551 else if (action == ELM_XDND_ACTION_DESCRIPTION)
1552 act = ECORE_X_ATOM_XDND_ACTION_DESCRIPTION;
1553 return act;
1554}
1555
1556static Eina_Bool
1557_x11_dnd_position(void *data EINA_UNUSED, int etype EINA_UNUSED, void *ev)
1558{
1559 Ecore_X_Event_Xdnd_Position *pos = ev;
1560 Ecore_X_Rectangle rect = { 0, 0, 0, 0 };
1561 Dropable *dropable;
1562 Elm_Xdnd_Action act;
1563
1564 /* Need to send a status back */
1565 /* FIXME: Should check I can drop here */
1566 /* FIXME: Should highlight widget */
1567 dropable = _x11_dropable_find(pos->win);
1568 if (dropable)
1569 {
1570 Evas_Coord x, y, ox = 0, oy = 0;
1571
1572 act = _x11_dnd_action_map(pos->action);
1573 x = pos->position.x;
1574 y = pos->position.y;
1575 _dropable_coords_adjust(dropable, &x, &y);
1576 Evas *evas = _x11_evas_get_from_xwin(pos->win);
1577 Eina_List *dropable_list = evas ? _dropable_list_geom_find(evas, x, y) : NULL;
1578 /* check if there is dropable (obj) can accept this drop */
1579 if (dropable_list)
1580 {
1581 Elm_Sel_Format saved_format = _dnd_types_to_format(savedtypes.types, savedtypes.ntypes);
1582 Eina_List *l;
1583 Eina_Bool found = EINA_FALSE;
1584
1585 EINA_LIST_FOREACH(dropable_list, l, dropable)
1586 {
1587 Dropable_Cbs *cbs;
1588 Eina_Inlist *itr;
1589 EINA_INLIST_FOREACH_SAFE(dropable->cbs_list, itr, cbs)
1590 {
1591 Elm_Sel_Format common_fmt = saved_format & cbs->types;
1592 if (common_fmt)
1593 {
1594 /* We found a target that can accept this type of data */
1595 int i, min_index = CNP_N_ATOMS;
1596 /* We have to find the first atom that corresponds to one
1597 * of the supported data types. */
1598 for (i = 0; i < savedtypes.ntypes; i++)
1599 {
1600 Cnp_Atom *atom = eina_hash_find(_types_hash, savedtypes.types[i]);
1601 if (atom && (atom->formats & common_fmt))
1602 {
1603 int atom_idx = (atom - _atoms);
1604 if (min_index > atom_idx) min_index = atom_idx;
1605 }
1606 }
1607 if (min_index != CNP_N_ATOMS)
1608 {
1609 cnp_debug("Found atom %s\n", _atoms[min_index].name);
1610 found = EINA_TRUE;
1611 dropable->last.type = _atoms[min_index].name;
1612 dropable->last.format = common_fmt;
1613 break;
1614 }
1615 }
1616 }
1617 if (found) break;
1618 }
1619 if (found)
1620 {
1621 Dropable *d = NULL;
1622 Eina_Rectangle inter_rect = {0, 0, 0, 0};
1623 int idx = 0;
1624 EINA_LIST_FOREACH(dropable_list, l, d)
1625 {
1626 if (idx == 0)
1627 {
1628 evas_object_geometry_get(d->obj, &inter_rect.x, &inter_rect.y,
1629 &inter_rect.w, &inter_rect.h);
1630 }
1631 else
1632 {
1633 Eina_Rectangle cur_rect;
1634 evas_object_geometry_get(d->obj, &cur_rect.x, &cur_rect.y,
1635 &cur_rect.w, &cur_rect.h);
1636 if (!eina_rectangle_intersection(&inter_rect, &cur_rect)) continue;
1637 }
1638 idx++;
1639 }
1640 rect.x = inter_rect.x;
1641 rect.y = inter_rect.y;
1642 rect.width = inter_rect.w;
1643 rect.height = inter_rect.h;
1644 ecore_x_dnd_send_status(EINA_TRUE, EINA_FALSE, rect, pos->action);
1645 cnp_debug("dnd position %i %i %p\n", x - ox, y - oy, dropable);
1646 _x11_dnd_dropable_handle(dropable, x - ox, y - oy, act);
1647 // CCCCCCC: call dnd exit on last obj if obj != last
1648 // CCCCCCC: call drop position on obj
1649 }
1650 else
1651 {
1652 //if not: send false status
1653 ecore_x_dnd_send_status(EINA_FALSE, EINA_FALSE, rect, pos->action);
1654 cnp_debug("dnd position (%d, %d) not in obj\n", x, y);
1655 _x11_dnd_dropable_handle(NULL, 0, 0, act);
1656 // CCCCCCC: call dnd exit on last obj
1657 }
1658 eina_list_free(dropable_list);
1659 }
1660 else
1661 {
1662 ecore_x_dnd_send_status(EINA_FALSE, EINA_FALSE, rect, pos->action);
1663 cnp_debug("dnd position (%d, %d) has no drop\n", x, y);
1664 _x11_dnd_dropable_handle(NULL, 0, 0, act);
1665 }
1666 }
1667 else
1668 {
1669 ecore_x_dnd_send_status(EINA_FALSE, EINA_FALSE, rect, pos->action);
1670 }
1671 return EINA_TRUE;
1672}
1673
1674static Eina_Bool
1675_x11_dnd_leave(void *data EINA_UNUSED, int etype EINA_UNUSED, void *ev)
1676{
1677#ifdef DEBUGON
1678 cnp_debug("Leave %x\n", ((Ecore_X_Event_Xdnd_Leave *)ev)->win);
1679#else
1680 (void)ev;
1681#endif
1682 _x11_dnd_dropable_handle(NULL, 0, 0, ELM_XDND_ACTION_UNKNOWN);
1683 // CCCCCCC: call dnd exit on last obj if there was one
1684 // leave->win leave->source
1685 return EINA_TRUE;
1686}
1687
1688static Eina_Bool
1689_x11_dnd_drop(void *data EINA_UNUSED, int etype EINA_UNUSED, void *ev)
1690{
1691 Ecore_X_Event_Xdnd_Drop *drop;
1692 Dropable *dropable = NULL;
1693 Elm_Selection_Data ddata;
1694 Evas_Coord x = 0, y = 0;
1695 Elm_Xdnd_Action act = ELM_XDND_ACTION_UNKNOWN;
1696 Eina_List *l;
1697 Dropable_Cbs *cbs;
1698 Eina_Inlist *itr;
1699
1700 drop = ev;
1701
1702 cnp_debug("drops %p (%d)\n", drops, eina_list_count(drops));
1703 if (!(dropable = _x11_dropable_find(drop->win))) return EINA_TRUE;
1704
1705 /* Calculate real (widget relative) position */
1706 // - window position
1707 // - widget position
1708 savedtypes.x = drop->position.x;
1709 savedtypes.y = drop->position.y;
1710 _dropable_coords_adjust(dropable, &savedtypes.x, &savedtypes.y);
1711
1712 cnp_debug("Drop position is %d,%d\n", savedtypes.x, savedtypes.y);
1713
1714 EINA_LIST_FOREACH(drops, l, dropable)
1715 {
1716 if (dropable->last.in)
1717 {
1718 evas_object_geometry_get(dropable->obj, &x, &y, NULL, NULL);
1719 savedtypes.x -= x;
1720 savedtypes.y -= y;
1721 goto found;
1722 }
1723 }
1724
1725 cnp_debug("Didn't find a target\n");
1726 return EINA_TRUE;
1727
1728found:
1729 cnp_debug("0x%x\n", drop->win);
1730
1731 act = _x11_dnd_action_map(drop->action);
1732
1733 dropable->last.in = EINA_FALSE;
1734 cnp_debug("Last type: %s - Last format: %X\n", dropable->last.type, dropable->last.format);
1735 if ((!strcmp(dropable->last.type, text_uri)))
1736 {
1737 cnp_debug("We found a URI... (%scached) %s\n",
1738 savedtypes.imgfile ? "" : "not ",
1739 savedtypes.imgfile);
1740 if (savedtypes.imgfile)
1741 {
1742 ddata.x = savedtypes.x;
1743 ddata.y = savedtypes.y;
1744 ddata.action = act;
1745
1746 EINA_INLIST_FOREACH_SAFE(dropable->cbs_list, itr, cbs)
1747 {
1748 /* If it's markup that also supports images */
1749 if (cbs->types & ELM_SEL_FORMAT_IMAGE)
1750 {
1751 cnp_debug("Doing image insert (%s)\n", savedtypes.imgfile);
1752 ddata.format = ELM_SEL_FORMAT_IMAGE;
1753 ddata.data = (char *)savedtypes.imgfile;
1754 ddata.len = strlen(ddata.data);
1755 if ((cbs->types & dropable->last.format) && cbs->dropcb)
1756 cbs->dropcb(cbs->dropdata, dropable->obj, &ddata);
1757 }
1758 else
1759 {
1760 cnp_debug("Item doesn't support images... passing\n");
1761 }
1762 }
1763 ecore_x_dnd_send_finished();
1764 ELM_SAFE_FREE(savedtypes.imgfile, free);
1765 return EINA_TRUE;
1766 }
1767 else if (savedtypes.textreq)
1768 {
1769 /* Already asked: Pretend we asked now, and paste immediately when
1770 * it comes in */
1771 savedtypes.textreq = 0;
1772 ecore_x_dnd_send_finished();
1773 return EINA_TRUE;
1774 }
1775 }
1776
1777 cnp_debug("doing a request then: %s\n", dropable->last.type);
1778 _x11_selections[ELM_SEL_TYPE_XDND].xwin = drop->win;
1779 _x11_selections[ELM_SEL_TYPE_XDND].requestwidget = dropable->obj;
1780 _x11_selections[ELM_SEL_TYPE_XDND].requestformat = dropable->last.format;
1781 _x11_selections[ELM_SEL_TYPE_XDND].active = EINA_TRUE;
1782 _x11_selections[ELM_SEL_TYPE_XDND].action = act;
1783 ecore_x_selection_xdnd_request(drop->win, dropable->last.type);
1784 return EINA_TRUE;
1785}
1786
1787static Eina_Bool
1788_x11_dnd_status(void *data EINA_UNUSED, int etype EINA_UNUSED, void *ev)
1789{
1790 Ecore_X_Event_Xdnd_Status *status = ev;
1791
1792 doaccept = EINA_FALSE;
1793
1794 /* Only thing we care about: will accept */
1795 if ((status) && (status->will_accept))
1796 {
1797 cnp_debug("Will accept\n");
1798 doaccept = EINA_TRUE;
1799 }
1800 /* Won't accept */
1801 else
1802 {
1803 cnp_debug("Won't accept accept\n");
1804 }
1805 if (dragacceptcb)
1806 dragacceptcb(dragacceptdata, _x11_selections[ELM_SEL_TYPE_XDND].widget,
1807 doaccept);
1808 return EINA_TRUE;
1809}
1810
1811static void
1812_x11_win_rotation_changed_cb(void *data, const Efl_Event *event)
1813{
1814 Evas_Object *win = data;
1815 int rot = elm_win_rotation_get(event->object);
1816 elm_win_rotation_set(win, rot);
1817}
1818
1819static Eina_Bool
1820_x11_drag_mouse_up(void *data, int etype EINA_UNUSED, void *event)
1821{
1822 Ecore_X_Window xwin = (Ecore_X_Window)(long)data;
1823 Ecore_Event_Mouse_Button *ev = event;
1824
1825 if ((ev->buttons == 1) &&
1826 (ev->event_window == xwin))
1827 {
1828 Eina_Bool have_drops = EINA_FALSE;
1829 Eina_List *l;
1830 Dropable *dropable;
1831
1832 ecore_x_pointer_ungrab();
1833 ELM_SAFE_FREE(handler_up, ecore_event_handler_del);
1834 ELM_SAFE_FREE(handler_status, ecore_event_handler_del);
1835 ecore_x_dnd_self_drop();
1836
1837 cnp_debug("mouse up, xwin=%#llx\n", (unsigned long long)xwin);
1838
1839 EINA_LIST_FOREACH(drops, l, dropable)
1840 {
1841 if (xwin == _x11_elm_widget_xwin_get(dropable->obj))
1842 {
1843 have_drops = EINA_TRUE;
1844 break;
1845 }
1846 }
1847 if (!have_drops) ecore_x_dnd_aware_set(xwin, EINA_FALSE);
1848 if (dragdonecb) dragdonecb(dragdonedata, dragwidget);
1849 if (dragwin)
1850 {
1851 if (dragwidget)
1852 {
1853 if (elm_widget_is(dragwidget))
1854 {
1855 Evas_Object *win = elm_widget_top_get(dragwidget);
1856 if (win && efl_isa(win, EFL_UI_WIN_CLASS))
1857 efl_event_callback_del(win, EFL_UI_WIN_EVENT_ROTATION_CHANGED, _x11_win_rotation_changed_cb, dragwin);
1858 }
1859 }
1860
1861 if (!doaccept)
1862 { /* Commit animation when drag cancelled */
1863 /* Record final position of dragwin, then do animation */
1864 ecore_animator_timeline_add(0.3,
1865 _drag_cancel_animate, dragwin);
1866 }
1867 else
1868 { /* No animation drop was committed */
1869 Ecore_X_Window xdragwin = _x11_elm_widget_xwin_get(dragwin);
1870 ecore_x_window_ignore_set(xdragwin, 0);
1871 evas_object_del(dragwin);
1872 }
1873
1874 dragwin = NULL; /* if not freed here, free in end of anim */
1875 }
1876
1877 dragdonecb = NULL;
1878 dragacceptcb = NULL;
1879 dragposcb = NULL;
1880 dragwidget = NULL;
1881 doaccept = EINA_FALSE;
1882 /* moved to _drag_cancel_animate
1883 if (dragwin)
1884 {
1885 evas_object_del(dragwin);
1886 dragwin = NULL;
1887 }
1888 */
1889 }
1890 return EINA_TRUE;
1891}
1892
1893static void
1894_x11_drag_move(void *data EINA_UNUSED, Ecore_X_Xdnd_Position *pos)
1895{
1896 evas_object_move(dragwin,
1897 pos->position.x - _dragx, pos->position.y - _dragy);
1898 dragwin_x_end = pos->position.x - _dragx;
1899 dragwin_y_end = pos->position.y - _dragy;
1900 cnp_debug("dragevas: %p -> %p\n",
1901 dragwidget,
1902 evas_object_evas_get(dragwidget));
1903 if (dragposcb)
1904 dragposcb(dragposdata, dragwidget, pos->position.x, pos->position.y,
1905 dragaction);
1906}
1907
1908static Ecore_X_Window
1909_x11_elm_widget_xwin_get(const Evas_Object *obj)
1910{
1911 Evas_Object *top, *par;
1912 Ecore_X_Window xwin = 0;
1913
1914 if (elm_widget_is(obj))
1915 {
1916 top = elm_widget_top_get(obj);
1917 if (!top)
1918 {
1919 par = elm_widget_parent_widget_get(obj);
1920 if (par) top = elm_widget_top_get(par);
1921 }
1922 if (top && (efl_isa(top, EFL_UI_WIN_CLASS)))
1923 xwin = elm_win_xwindow_get(top);
1924 }
1925 if (!xwin)
1926 {
1927 Ecore_Evas *ee;
1928 Evas *evas = evas_object_evas_get(obj);
1929 if (!evas) return 0;
1930 ee = ecore_evas_ecore_evas_get(evas);
1931 if (!ee) return 0;
1932
1933 while(!xwin)
1934 {
1935 const char *engine_name = ecore_evas_engine_name_get(ee);
1936 if (!strcmp(engine_name, ELM_BUFFER))
1937 {
1938 ee = ecore_evas_buffer_ecore_evas_parent_get(ee);
1939 if (!ee) return 0;
1940 xwin = _elm_ee_xwin_get(ee);
1941 }
1942 else
1943 {
1944 /* In case the engine is not a buffer, we want to check once. */
1945 xwin = _elm_ee_xwin_get(ee);
1946 if (!xwin) return 0;
1947 }
1948 }
1949 }
1950 return xwin;
1951}
1952
1953static Eina_Bool
1954_x11_elm_cnp_init(void)
1955{
1956 int i;
1957 static int _init_count = 0;
1958
1959 if (_init_count > 0) return EINA_TRUE;
1960 _init_count++;
1961 for (i = 0; i < CNP_N_ATOMS; i++)
1962 {
1963 _atoms[i].x_atom = ecore_x_atom_get(_atoms[i].name);
1964 ecore_x_selection_converter_atom_add
1965 (_atoms[i].x_atom, _atoms[i].x_converter);
1966 }
1967 //XXX delete handlers?
1968 ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, _x11_selection_clear, NULL);
1969 ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, _x11_selection_notify, NULL);
1970 ecore_event_handler_add(ECORE_X_EVENT_FIXES_SELECTION_NOTIFY, _x11_fixes_selection_notify, NULL);
1971 return EINA_TRUE;
1972}
1973
1974static Eina_Bool
1975_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)
1976{
1977 X11_Cnp_Selection *sel;
1978
1979 _x11_elm_cnp_init();
1980 if ((!selbuf) && (format != ELM_SEL_FORMAT_IMAGE))
1981 return elm_object_cnp_selection_clear(obj, selection);
1982
1983 sel = _x11_selections + selection;
1984 if (sel->widget != obj && sel->loss_cb) sel->loss_cb(sel->loss_data, selection);
1985 if (sel->widget)
1986 evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL,
1987 _x11_sel_obj_del, sel);
1988 sel->active = EINA_TRUE;
1989 sel->widget = obj;
1990 sel->xwin = xwin;
1991 if (sel->set) sel->set(xwin, &selection, sizeof(Elm_Sel_Type));
1992 sel->format = format;
1993 sel->loss_cb = NULL;
1994 sel->loss_data = NULL;
1995
1996 evas_object_event_callback_add
1997 (sel->widget, EVAS_CALLBACK_DEL, _x11_sel_obj_del, sel);
1998
1999 ELM_SAFE_FREE(sel->selbuf, free);
2000 if (selbuf)
2001 {
2002 if (format == ELM_SEL_FORMAT_IMAGE)
2003 {
2004 // selbuf is actual image data, not text/string
2005 sel->selbuf = malloc(buflen + 1);
2006 if (!sel->selbuf)
2007 {
2008 elm_object_cnp_selection_clear(obj, selection);
2009 return EINA_FALSE;
2010 }
2011 memcpy(sel->selbuf, selbuf, buflen);
2012 sel->selbuf[buflen] = 0;
2013 }
2014 else
2015 sel->selbuf = strdup((char*)selbuf);
2016 }
2017
2018 return _local_elm_cnp_selection_set(obj, selection, format, selbuf, buflen);
2019}
2020
2021static void
2022_x11_elm_cnp_selection_loss_callback_set(Evas_Object *obj EINA_UNUSED, Elm_Sel_Type selection, Elm_Selection_Loss_Cb func, const void *data)
2023{
2024 X11_Cnp_Selection *sel;
2025
2026 _x11_elm_cnp_init();
2027 sel = _x11_selections + selection;
2028 sel->loss_cb = func;
2029 sel->loss_data = (void *)data;
2030}
2031
2032static Eina_Bool
2033_x11_elm_object_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type selection)
2034{
2035 X11_Cnp_Selection *sel;
2036
2037 _x11_elm_cnp_init();
2038
2039 sel = _x11_selections + selection;
2040
2041 /* No longer this selection: Consider it gone! */
2042 if ((!sel->active) || (sel->widget != obj)) return EINA_TRUE;
2043
2044 if (sel->widget)
2045 evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL,
2046 _x11_sel_obj_del, sel);
2047 if (sel->requestwidget)
2048 evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL,
2049 _x11_sel_obj_del2, sel);
2050 sel->widget = NULL;
2051 sel->requestwidget = NULL;
2052 sel->loss_cb = NULL;
2053 sel->loss_data = NULL;
2054
2055 sel->active = EINA_FALSE;
2056 ELM_SAFE_FREE(sel->selbuf, free);
2057 sel->clear();
2058
2059 return _local_elm_object_cnp_selection_clear(obj, selection);
2060}
2061
2062static Eina_Bool
2063_x11_elm_cnp_selection_get(Ecore_X_Window xwin, const Evas_Object *obj, Elm_Sel_Type selection,
2064 Elm_Sel_Format format, Elm_Drop_Cb datacb,
2065 void *udata)
2066{
2067 X11_Cnp_Selection *sel;
2068
2069 _x11_elm_cnp_init();
2070
2071 sel = _x11_selections + selection;
2072 if (sel->active)
2073 return _local_elm_cnp_selection_get(obj, selection, format, datacb, udata);
2074
2075 if (sel->requestwidget)
2076 evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL,
2077 _x11_sel_obj_del2, sel);
2078 sel->requestformat = format;
2079 sel->requestwidget = (Evas_Object *)obj;
2080 sel->xwin = xwin;
2081 sel->request(xwin, ECORE_X_SELECTION_TARGET_TARGETS);
2082 sel->datacb = datacb;
2083 sel->udata = udata;
2084
2085 evas_object_event_callback_add
2086 (sel->requestwidget, EVAS_CALLBACK_DEL, _x11_sel_obj_del2, sel);
2087
2088 return EINA_TRUE;
2089}
2090
2091static Eina_Bool
2092_x11_elm_drop_target_add(Evas_Object *obj, Elm_Sel_Format format,
2093 Elm_Drag_State entercb, void *enterdata,
2094 Elm_Drag_State leavecb, void *leavedata,
2095 Elm_Drag_Pos poscb, void *posdata,
2096 Elm_Drop_Cb dropcb, void *dropdata)
2097{
2098 Dropable *dropable = NULL;
2099 Dropable_Cbs *cbs = NULL;
2100 Ecore_X_Window xwin = _x11_elm_widget_xwin_get(obj);
2101 Eina_List *l;
2102 Eina_Bool first = !drops;
2103 Eina_Bool have_drops = EINA_FALSE;
2104
2105 _x11_elm_cnp_init();
2106
2107 /* Is this the first? */
2108 EINA_LIST_FOREACH(drops, l, dropable)
2109 {
2110 if (xwin == _x11_elm_widget_xwin_get(dropable->obj))
2111 {
2112 have_drops = EINA_TRUE;
2113 break;
2114 }
2115 }
2116 dropable = NULL; // In case of error, we don't want to free it
2117
2118 cbs = calloc(1, sizeof(*cbs));
2119 if (!cbs) return EINA_FALSE;
2120
2121 cbs->entercb = entercb;
2122 cbs->enterdata = enterdata;
2123 cbs->leavecb = leavecb;
2124 cbs->leavedata = leavedata;
2125 cbs->poscb = poscb;
2126 cbs->posdata = posdata;
2127 cbs->dropcb = dropcb;
2128 cbs->dropdata = dropdata;
2129 cbs->types = format;
2130
2131 dropable = efl_key_data_get(obj, "__elm_dropable");
2132 if (!dropable)
2133 {
2134 /* Create new drop */
2135 dropable = calloc(1, sizeof(Dropable));
2136 if (!dropable) goto error;
2137 dropable->last.in = EINA_FALSE;
2138 drops = eina_list_append(drops, dropable);
2139 if (!drops) goto error;
2140 dropable->obj = obj;
2141 efl_key_data_set(obj, "__elm_dropable", dropable);
2142 }
2143 dropable->cbs_list = eina_inlist_append(dropable->cbs_list, EINA_INLIST_GET(cbs));
2144
2145 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
2146 _all_drop_targets_cbs_del, obj);
2147 if (!have_drops) ecore_x_dnd_aware_set(xwin, EINA_TRUE);
2148
2149 /* TODO BUG: should handle dnd-aware per window, not just the first
2150 * window that requested it! */
2151 /* If not the first: We're done */
2152 if (!first) return EINA_TRUE;
2153
2154 cnp_debug("Adding drop target calls xwin=%#llx\n", (unsigned long long)xwin);
2155 handler_enter = ecore_event_handler_add(ECORE_X_EVENT_XDND_ENTER,
2156 _x11_dnd_enter, NULL);
2157 handler_leave = ecore_event_handler_add(ECORE_X_EVENT_XDND_LEAVE,
2158 _x11_dnd_leave, NULL);
2159 handler_pos = ecore_event_handler_add(ECORE_X_EVENT_XDND_POSITION,
2160 _x11_dnd_position, NULL);
2161 handler_drop = ecore_event_handler_add(ECORE_X_EVENT_XDND_DROP,
2162 _x11_dnd_drop, NULL);
2163 return EINA_TRUE;
2164error:
2165 free(cbs);
2166 free(dropable);
2167 return EINA_FALSE;
2168}
2169
2170static Eina_Bool
2171_x11_elm_drop_target_del(Evas_Object *obj, Elm_Sel_Format format,
2172 Elm_Drag_State entercb, void *enterdata,
2173 Elm_Drag_State leavecb, void *leavedata,
2174 Elm_Drag_Pos poscb, void *posdata,
2175 Elm_Drop_Cb dropcb, void *dropdata)
2176{
2177 Dropable *dropable = NULL;
2178 Eina_List *l;
2179 Ecore_X_Window xwin;
2180 Eina_Bool have_drops = EINA_FALSE;
2181
2182 _x11_elm_cnp_init();
2183
2184 if (!_local_elm_drop_target_del(obj, format, entercb, enterdata,
2185 leavecb, leavedata, poscb, posdata, dropcb, dropdata))
2186 {
2187 return EINA_FALSE;
2188 }
2189
2190 /* TODO BUG: we should handle dnd-aware per window, not just the last that released it */
2191
2192 /* If still drops there: All fine.. continue */
2193 if (drops) return EINA_TRUE;
2194
2195 cnp_debug("Disabling DND\n");
2196 xwin = _x11_elm_widget_xwin_get(obj);
2197 EINA_LIST_FOREACH(drops, l, dropable)
2198 {
2199 if (xwin == _x11_elm_widget_xwin_get(dropable->obj))
2200 {
2201 have_drops = EINA_TRUE;
2202 break;
2203 }
2204 }
2205 if (!have_drops) ecore_x_dnd_aware_set(xwin, EINA_FALSE);
2206
2207 if (!drops)
2208 {
2209 ELM_SAFE_FREE(handler_pos, ecore_event_handler_del);
2210 ELM_SAFE_FREE(handler_drop, ecore_event_handler_del);
2211 ELM_SAFE_FREE(handler_enter, ecore_event_handler_del);
2212 ELM_SAFE_FREE(handler_leave, ecore_event_handler_del);
2213 }
2214
2215 ELM_SAFE_FREE(savedtypes.imgfile, free);
2216
2217 return EINA_TRUE;
2218}
2219
2220static void
2221_x11_drag_target_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *info EINA_UNUSED)
2222{
2223 X11_Cnp_Selection *sel = _x11_selections + ELM_SEL_TYPE_XDND;
2224
2225 if (dragwidget == obj)
2226 {
2227 sel->widget = NULL;
2228 dragwidget = NULL;
2229 }
2230}
2231
2232static Eina_Bool
2233_x11_elm_drag_start(Evas_Object *obj, Elm_Sel_Format format, const char *data,
2234 Elm_Xdnd_Action action,
2235 Elm_Drag_Icon_Create_Cb createicon, void *createdata,
2236 Elm_Drag_Pos dragpos, void *dragdata,
2237 Elm_Drag_Accept acceptcb, void *acceptdata,
2238 Elm_Drag_State dragdone, void *donecbdata)
2239{
2240 Ecore_X_Window xwin = _x11_elm_widget_xwin_get(obj);
2241 Ecore_X_Window xdragwin;
2242 X11_Cnp_Selection *sel;
2243 Elm_Sel_Type xdnd = ELM_SEL_TYPE_XDND;
2244 Ecore_Evas *ee;
2245 int x, y, x2 = 0, y2 = 0, x3, y3;
2246 Evas_Object *icon = NULL;
2247 int w = 0, h = 0;
2248 int ex, ey, ew, eh;
2249 Ecore_X_Atom actx;
2250 int i;
2251 int xr, yr, rot;
2252
2253 _x11_elm_cnp_init();
2254
2255 cnp_debug("starting drag... %p\n", obj);
2256
2257 if (dragwin)
2258 {
2259 cnp_debug("another obj is dragging...\n");
2260 return EINA_FALSE;
2261 }
2262
2263 ecore_x_dnd_types_set(xwin, NULL, 0);
2264 for (i = CNP_ATOM_LISTING_ATOMS + 1; i < CNP_N_ATOMS; i++)
2265 {
2266 if (format == ELM_SEL_FORMAT_TARGETS || (_atoms[i].formats & format))
2267 {
2268 ecore_x_dnd_type_set(xwin, _atoms[i].name, EINA_TRUE);
2269 cnp_debug("set dnd type: %s\n", _atoms[i].name);
2270 }
2271 }
2272
2273 sel = _x11_selections + ELM_SEL_TYPE_XDND;
2274 sel->active = EINA_TRUE;
2275 sel->widget = obj;
2276 sel->format = format;
2277 sel->selbuf = data ? strdup(data) : NULL;
2278 sel->action = action;
2279 dragwidget = obj;
2280 dragaction = action;
2281
2282 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
2283 _x11_drag_target_del, obj);
2284 /* TODO BUG: should NEVER have these as globals! They should be per context (window). */
2285 dragposcb = dragpos;
2286 dragposdata = dragdata;
2287 dragacceptcb = acceptcb;
2288 dragacceptdata = acceptdata;
2289 dragdonecb = dragdone;
2290 dragdonedata = donecbdata;
2291 /* TODO BUG: should increase dnd-awareness, in case it's drop target as well. See _x11_drag_mouse_up() */
2292 ecore_x_dnd_aware_set(xwin, EINA_TRUE);
2293 ecore_x_dnd_callback_pos_update_set(_x11_drag_move, NULL);
2294 ecore_x_dnd_self_begin(xwin, (unsigned char *)&xdnd, sizeof(Elm_Sel_Type));
2295 actx = _x11_dnd_action_rev_map(dragaction);
2296 ecore_x_dnd_source_action_set(actx);
2297 ecore_x_pointer_grab(xwin);
2298 handler_up = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
2299 _x11_drag_mouse_up,
2300 (void *)(long)xwin);
2301 handler_status = ecore_event_handler_add(ECORE_X_EVENT_XDND_STATUS,
2302 _x11_dnd_status, NULL);
2303 dragwin = elm_win_add(NULL, "Elm-Drag", ELM_WIN_DND);
2304 elm_win_alpha_set(dragwin, EINA_TRUE);
2305 elm_win_override_set(dragwin, EINA_TRUE);
2306 xdragwin = _x11_elm_widget_xwin_get(dragwin);
2307 ecore_x_window_ignore_set(xdragwin, 1);
2308
2309 /* dragwin has to be rotated as the main window is */
2310 if (elm_widget_is(obj))
2311 {
2312 Evas_Object *win = elm_widget_top_get(obj);
2313 if (win && efl_isa(win, EFL_UI_WIN_CLASS))
2314 {
2315 elm_win_rotation_set(dragwin, elm_win_rotation_get(win));
2316 efl_event_callback_add(win, EFL_UI_WIN_EVENT_ROTATION_CHANGED, _x11_win_rotation_changed_cb, dragwin);
2317 }
2318 }
2319
2320 if (createicon)
2321 {
2322 Evas_Coord xoff = 0, yoff = 0;
2323
2324 icon = createicon(createdata, dragwin, &xoff, &yoff);
2325 if (icon)
2326 {
2327 x2 = xoff;
2328 y2 = yoff;
2329 evas_object_geometry_get(icon, NULL, NULL, &w, &h);
2330 }
2331 }
2332 else
2333 {
2334 icon = elm_icon_add(dragwin);
2335 evas_object_size_hint_weight_set(icon, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
2336 // need to resize
2337 }
2338 elm_win_resize_object_add(dragwin, icon);
2339
2340 /* Position subwindow appropriately */
2341 ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
2342 ecore_evas_geometry_get(ee, &ex, &ey, &ew, &eh);
2343 evas_object_resize(dragwin, w, h);
2344
2345 evas_object_show(icon);
2346 evas_object_show(dragwin);
2347 evas_pointer_canvas_xy_get(evas_object_evas_get(obj), &x3, &y3);
2348
2349 rot = ecore_evas_rotation_get(ee);
2350 switch (rot)
2351 {
2352 case 90:
2353 xr = y3;
2354 yr = ew - x3;
2355 _dragx = y3 - y2;
2356 _dragy = x3 - x2;
2357 break;
2358 case 180:
2359 xr = ew - x3;
2360 yr = eh - y3;
2361 _dragx = x3 - x2;
2362 _dragy = y3 - y2;
2363 break;
2364 case 270:
2365 xr = eh - y3;
2366 yr = x3;
2367 _dragx = y3 - y2;
2368 _dragy = x3 - x2;
2369 break;
2370 default:
2371 xr = x3;
2372 yr = y3;
2373 _dragx = x3 - x2;
2374 _dragy = y3 - y2;
2375 break;
2376 }
2377 x = ex + xr - _dragx;
2378 y = ey + yr - _dragy;
2379 evas_object_move(dragwin, x, y);
2380 dragwin_x_start = dragwin_x_end = x;
2381 dragwin_y_start = dragwin_y_end = y;
2382
2383 return EINA_TRUE;
2384}
2385
2386static Eina_Bool
2387_x11_elm_drag_action_set(Evas_Object *obj, Elm_Xdnd_Action action)
2388{
2389 Ecore_X_Atom actx;
2390
2391 _x11_elm_cnp_init();
2392 if (!dragwin) return EINA_FALSE;
2393
2394 if (dragwidget != obj) return EINA_FALSE;
2395 if (dragaction == action) return EINA_TRUE;
2396 dragaction = action;
2397 actx = _x11_dnd_action_rev_map(dragaction);
2398 ecore_x_dnd_source_action_set(actx);
2399 return EINA_TRUE;
2400}
2401
2402static Eina_Bool
2403_x11_elm_selection_selection_has_owner(Evas_Object *obj EINA_UNUSED)
2404{
2405 _x11_elm_cnp_init();
2406 return !!ecore_x_selection_owner_get(ECORE_X_ATOM_SELECTION_CLIPBOARD);
2407}
2408
2409#endif
2410
2411#ifdef HAVE_ELEMENTARY_WL2
2412struct _Wl_Cnp_Selection
2413{
2414 char *selbuf;
2415 int buflen;
2416
2417 Evas_Object *widget;
2418 Evas_Object *requestwidget;
2419
2420 void *udata;
2421 Elm_Sel_Type seltype;
2422 Elm_Sel_Format requestformat;
2423 Elm_Drop_Cb datacb;
2424
2425 Elm_Selection_Loss_Cb loss_cb;
2426 void *loss_data;
2427
2428 Elm_Sel_Format format;
2429 Ecore_Wl2_Window *win;
2430 Elm_Xdnd_Action action;
2431 uint32_t selection_serial;
2432 uint32_t drag_serial;
2433
2434 Eina_Bool active : 1;
2435};
2436
2437static Eina_Bool _wl_elm_cnp_init(void);
2438
2439static Wl_Cnp_Selection wl_cnp_selection =
2440{
2441 0, 0, NULL, NULL,
2442 NULL, 0, 0, NULL, NULL, NULL,
2443 0, NULL, 0, EINA_FALSE
2444};
2445
2446static void _wl_sel_obj_del2(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED);
2447static 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);
2448static 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);
2449static Eina_Bool _wl_elm_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type selection);
2450
2451static Eina_Bool _wl_selection_send(void *udata, int type EINA_UNUSED, void *event);
2452static Eina_Bool _wl_selection_receive(void *udata, int type EINA_UNUSED, void *event);
2453
2454static Eina_Bool _wl_elm_dnd_init(void);
2455static 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);
2456static 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);
2457
2458static Eina_Bool _wl_elm_drag_action_set(Evas_Object *obj, Elm_Xdnd_Action action);
2459static 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);
2460
2461static void _wl_drag_source_del(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event EINA_UNUSED);
2462
2463static Eina_Bool _wl_dnd_enter(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
2464static Eina_Bool _wl_dnd_leave(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
2465static Eina_Bool _wl_dnd_position(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
2466static Eina_Bool _wl_dnd_drop(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
2467/* static Eina_Bool _wl_dnd_offer(void *data EINA_UNUSED, int type EINA_UNUSED, void *event); */
2468
2469static Eina_Bool _wl_dnd_receive(void *data, int type EINA_UNUSED, void *event);
2470static Eina_Bool _wl_dnd_end(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED);
2471static void _wl_dropable_data_handle(Wl_Cnp_Selection *sel, Ecore_Wl2_Event_Offer_Data_Ready *ev);
2472
2473static Dropable *_wl_dropable_find(unsigned int win);
2474static void _wl_dropable_handle(Dropable *drop, Evas_Coord x, Evas_Coord y);
2475static void _wl_dropable_all_clean(unsigned int win);
2476static Eina_Bool _wl_drops_accept(const char *type);
2477static Ecore_Wl2_Window *_wl_elm_widget_window_get(const Evas_Object *obj);
2478static Evas * _wl_evas_get_from_win(unsigned int win);
2479
2480static Eina_Bool
2481_wl_is_uri_type_data(const char *data, int len)
2482{
2483 char *p;
2484 if (len < 6) return EINA_FALSE;
2485
2486 p = (char *)data;
2487 if (!p) return EINA_FALSE;
2488 if (strncmp(p, "file:/", 6))
2489 {
2490 if (*p != '/') return EINA_FALSE;
2491 }
2492 return EINA_TRUE;
2493}
2494
2495static Eina_Bool
2496_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)
2497{
2498 cnp_debug("in\n");
2499 if (!data_ret) return EINA_FALSE;
2500
2501 const char *sep = "\n";
2502 char *aret;
2503 int len = 0;
2504 int i = 0;
2505 Elm_Sel_Format formats = ELM_SEL_FORMAT_NONE;
2506 Eina_Bool is_uri = EINA_FALSE;
2507
2508 if (sel->format)
2509 {
2510 formats = sel->format;
2511 is_uri = _wl_is_uri_type_data(sel->selbuf, sel->buflen);
2512 }
2513 else
2514 {
2515 Cnp_Atom *atom = eina_hash_find(_types_hash, target);
2516 if (atom)
2517 formats = atom->formats;
2518 }
2519 for (i = 0; i < CNP_N_ATOMS; i++)
2520 {
2521 if (formats & _atoms[i].formats)
2522 {
2523 if ((is_uri) ||
2524 ((!is_uri) && strcmp(_atoms[i].name, "text/uri-list")))
2525 len += strlen(_atoms[i].name) + strlen(sep);
2526 }
2527 }
2528 len++; //terminating null byte
2529 aret = calloc(1, len * sizeof(char));
2530 if (!aret) return EINA_FALSE;
2531 for (i = 0; i < CNP_N_ATOMS; i++)
2532 {
2533 if (formats & _atoms[i].formats)
2534 {
2535 if ((is_uri) ||
2536 ((!is_uri) && strcmp(_atoms[i].name, "text/uri-list")))
2537 {
2538 aret = strcat(aret, _atoms[i].name);
2539 aret = strcat(aret, sep);
2540 }
2541 }
2542 }
2543 *data_ret = aret;
2544 if (size_ret) *size_ret = len;
2545
2546 return EINA_TRUE;
2547}
2548
2549static Eina_Bool
2550_wl_general_converter(char *target, Wl_Cnp_Selection *sel EINA_UNUSED, void *data, int size, void **data_ret, int *size_ret)
2551{
2552 Elm_Sel_Format formats = ELM_SEL_FORMAT_NONE;
2553 Cnp_Atom *atom = NULL;
2554
2555 cnp_debug("in\n");
2556
2557 atom = eina_hash_find(_types_hash, target);
2558 if (atom)
2559 formats = atom->formats;
2560 if (formats == ELM_SEL_FORMAT_NONE)
2561 {
2562 if (data_ret)