2 # include "elementary_config.h"
4 #include <Elementary.h>
15 CNP_ATOM_LISTING_ATOMS = CNP_ATOM_ATOM,
17 CNP_ATOM_text_urilist,
18 CNP_ATOM_text_x_vcard,
29 // CNP_ATOM_text_html_utf8,
30 // CNP_ATOM_text_html,
33 CNP_ATOM_COMPOUND_TEXT,
35 CNP_ATOM_text_plain_utf8,
41 typedef struct _Tmp_Info Tmp_Info;
42 typedef struct _Saved_Type Saved_Type;
43 typedef struct _Cnp_Escape Cnp_Escape;
44 typedef struct _Dropable Dropable;
45 static Eina_Bool doaccept = EINA_FALSE;
73 /* FIXME: Cache window */
75 Elm_Drag_State entercb;
76 Elm_Drag_State leavecb;
89 struct _Item_Container_Drop_Info
90 { /* Info kept for containers to support drop */
92 Elm_Xy_Item_Get_Cb itemgetcb;
93 Elm_Drop_Item_Container_Cb dropcb;
94 Elm_Drag_Item_Container_Pos poscb;
96 typedef struct _Item_Container_Drop_Info Item_Container_Drop_Info;
106 typedef struct _Anim_Icon Anim_Icon;
108 struct _Item_Container_Drag_Info
109 { /* Info kept for containers to support drag */
111 Ecore_Timer *tm; /* When this expires, start drag */
112 double anim_tm; /* Time period to set tm */
113 double tm_to_drag; /* Time period to set tm */
114 Elm_Xy_Item_Get_Cb itemgetcb;
115 Elm_Item_Container_Data_Get_Cb data_get;
117 Evas_Coord x_down; /* Mouse down x cord when drag starts */
118 Evas_Coord y_down; /* Mouse down y cord when drag starts */
120 /* Some extra information needed to impl default anim */
122 Eina_List *icons; /* List of icons to animate (Anim_Icon) */
123 int final_icon_w; /* We need the w and h of the final icon for the animation */
127 Elm_Drag_User_Info user_info;
129 typedef struct _Item_Container_Drag_Info Item_Container_Drag_Info;
131 static int _elm_cnp_init_count = 0;
132 /* Stringshared, so I can just compare pointers later */
133 static const char *text_uri;
134 /* Data for DND in progress */
135 static Saved_Type savedtypes = { NULL, NULL, 0, 0, 0, EINA_FALSE };
137 /* TODO BUG: should NEVER have these as globals! They should be per context (window). */
138 static Elm_Drag_Pos dragposcb = NULL;
139 static Elm_Drag_Accept dragacceptcb = NULL;
140 static Elm_Drag_State dragdonecb = NULL;
141 static void *dragposdata = NULL;
142 static void *dragacceptdata = NULL;
143 static void *dragdonedata = NULL;
144 static Evas_Object *dragwidget = NULL;
145 static Elm_Xdnd_Action dragaction = ELM_XDND_ACTION_UNKNOWN;
147 static Eina_List *cont_drop_tg = NULL; /* List of Item_Container_Drop_Info */
148 static Eina_List *cont_drag_tg = NULL; /* List of Item_Container_Drag_Info */
150 static void _cont_obj_mouse_up( void *data, Evas *e, Evas_Object *obj, void *event_info);
151 static void _cont_obj_mouse_move( void *data, Evas *e, Evas_Object *obj, void *event_info);
153 /* Drag & Drop functions */
154 /* FIXME: Way too many globals */
155 static Eina_List *drops = NULL;
156 static Evas_Object *dragwin = NULL;
157 static int dragwin_x_start, dragwin_y_start;
158 static int dragwin_x_end, dragwin_y_end;
159 static int _dragx = 0, _dragy = 0;
160 static Ecore_Event_Handler *handler_pos = NULL;
161 static Ecore_Event_Handler *handler_drop = NULL;
162 static Ecore_Event_Handler *handler_enter = NULL;
163 static Ecore_Event_Handler *handler_status = NULL;
164 static Ecore_Event_Handler *handler_leave = NULL;
165 static Ecore_Event_Handler *handler_up = NULL;
167 static Tmp_Info *_tempfile_new (int size);
168 static int _tmpinfo_free (Tmp_Info *tmp);
169 static Eina_Bool _pasteimage_append (char *file, Evas_Object *entry);
170 static void _entry_insert_filter(Evas_Object *entry, char *str); // TIZEN ONLY
174 # define cnp_debug(x...) fprintf(stderr, __FILE__": " x)
176 # define cnp_debug(x...) do { } while (0)
179 // x11 specific stuff
180 ////////////////////////////////////////////////////////////////////////////
181 #ifdef HAVE_ELEMENTARY_X
182 #define ARRAYINIT(foo) [foo] =
184 typedef struct _X11_Cnp_Selection X11_Cnp_Selection;
185 typedef struct _X11_Cnp_Atom X11_Cnp_Atom;
187 typedef Eina_Bool (*X11_Converter_Fn_Cb) (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
188 typedef int (*X11_Response_Handler_Cb) (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *);
189 typedef int (*X11_Notify_Handler_Cb) (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *);
191 struct _X11_Cnp_Selection
196 Evas_Object *requestwidget;
198 Elm_Sel_Format requestformat;
200 Eina_Bool (*set) (Ecore_X_Window, const void *data, int size);
201 Eina_Bool (*clear) (void);
202 void (*request) (Ecore_X_Window, const char *target);
203 Elm_Selection_Loss_Cb loss_cb;
206 Elm_Sel_Format format;
207 Ecore_X_Selection ecore_sel;
209 Elm_Xdnd_Action action;
211 Eina_Bool active : 1;
217 Elm_Sel_Format formats;
218 /* Called by ecore to do conversion */
219 X11_Converter_Fn_Cb converter;
220 X11_Response_Handler_Cb response;
221 X11_Notify_Handler_Cb notify;
226 static void _x11_sel_obj_del (void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__);
227 static void _x11_sel_obj_del2 (void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__);
228 static Eina_Bool _x11_selection_clear (void *udata __UNUSED__, int type, void *event);
229 static Eina_Bool _x11_selection_notify (void *udata __UNUSED__, int type, void *event);
230 static Eina_Bool _x11_targets_converter (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
231 static Eina_Bool _x11_text_converter (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
232 static Eina_Bool _x11_general_converter (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
233 static Eina_Bool _x11_image_converter (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
234 static Eina_Bool _x11_vcard_send (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
235 //TIZEN ONLY : static Eina_Bool _x11_is_uri_type_data (X11_Cnp_Selection *sel __UNUSED__, Ecore_X_Event_Selection_Notify *notify);
236 static int _x11_response_handler_targets (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *);
237 static int _x11_notify_handler_targets (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify);
238 static int _x11_notify_handler_text (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify);
239 static int _x11_notify_handler_image (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify);
240 static int _x11_notify_handler_uri (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify);
241 //static int _x11_notify_handler_html (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify);
242 static int _x11_notify_handler_edje (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify); // TIZEN ONLY
243 static int _x11_vcard_receive (X11_Cnp_Selection *sed, Ecore_X_Event_Selection_Notify *notify);
244 static Eina_Bool _x11_dnd_enter (void *data __UNUSED__, int etype __UNUSED__, void *ev);
245 static Eina_Bool _x11_dnd_drop (void *data __UNUSED__, int etype __UNUSED__, void *ev);
246 static Eina_Bool _x11_dnd_position (void *data __UNUSED__, int etype __UNUSED__, void *ev);
247 static Eina_Bool _x11_dnd_status (void *data __UNUSED__, int etype __UNUSED__, void *ev);
248 static Eina_Bool _x11_drag_mouse_up (void *data, int etype __UNUSED__, void *event);
249 static void _x11_drag_move (void *data __UNUSED__, Ecore_X_Xdnd_Position *pos);
251 static Ecore_X_Window _x11_elm_widget_xwin_get (const Evas_Object *obj);
253 static Eina_Bool _x11_elm_cnp_init (void);
254 static Eina_Bool _x11_elm_cnp_selection_set (Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, const void *selbuf, size_t buflen);
255 static void _x11_elm_cnp_selection_loss_callback_set(Evas_Object *obj __UNUSED__, Elm_Sel_Type selection, Elm_Selection_Loss_Cb func, const void *data);
256 static Eina_Bool _x11_elm_object_cnp_selection_clear (Evas_Object *obj, Elm_Sel_Type selection);
257 static Eina_Bool _x11_elm_cnp_selection_get (Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata);
258 static Eina_Bool _x11_elm_drop_target_add (Evas_Object *obj, Elm_Sel_Format format,
259 Elm_Drag_State entercb, void *enterdata,
260 Elm_Drag_State leavecb, void *leavedata,
261 Elm_Drag_Pos poscb, void *posdata,
262 Elm_Drop_Cb dropcb, void *cbdata);
263 static Eina_Bool _x11_elm_drop_target_del (Evas_Object *obj);
264 static Eina_Bool _x11_elm_selection_selection_has_owner (Evas_Object *obj __UNUSED__);
266 static X11_Cnp_Atom _x11_atoms[CNP_N_ATOMS] = {
267 [CNP_ATOM_TARGETS] = {
269 ELM_SEL_FORMAT_TARGETS,
270 _x11_targets_converter,
271 _x11_response_handler_targets,
272 _x11_notify_handler_targets,
276 "ATOM", // for opera browser
277 ELM_SEL_FORMAT_TARGETS,
278 _x11_targets_converter,
279 _x11_response_handler_targets,
280 _x11_notify_handler_targets,
284 "application/x-elementary-markup",
285 ELM_SEL_FORMAT_MARKUP,
286 _x11_general_converter,
288 //NULL, // TIZEN ONLY
289 _x11_notify_handler_edje, // TIZEN ONLY
292 [CNP_ATOM_text_uri] = {
294 //ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_IMAGE, /* Either images or entries */ // TIZEN ONLY
295 ELM_SEL_FORMAT_IMAGE, // TIZEN ONLY
296 _x11_general_converter,
298 _x11_notify_handler_uri,
301 [CNP_ATOM_text_urilist] = {
303 ELM_SEL_FORMAT_IMAGE,
304 _x11_general_converter,
306 _x11_notify_handler_uri,
309 [CNP_ATOM_text_x_vcard] = {
311 ELM_SEL_FORMAT_VCARD,
312 _x11_vcard_send, NULL,
313 _x11_vcard_receive, 0
315 [CNP_ATOM_image_png] = {
317 ELM_SEL_FORMAT_IMAGE,
318 _x11_image_converter,
320 _x11_notify_handler_image,
323 [CNP_ATOM_image_jpeg] = {
325 ELM_SEL_FORMAT_IMAGE,
326 _x11_image_converter,
328 _x11_notify_handler_image,/* Raw image data is the same */
331 [CNP_ATOM_image_bmp] = {
333 ELM_SEL_FORMAT_IMAGE,
334 _x11_image_converter,
336 _x11_notify_handler_image,/* Raw image data is the same */
339 [CNP_ATOM_image_gif] = {
341 ELM_SEL_FORMAT_IMAGE,
342 _x11_image_converter,
344 _x11_notify_handler_image,/* Raw image data is the same */
347 [CNP_ATOM_image_tiff] = {
349 ELM_SEL_FORMAT_IMAGE,
350 _x11_image_converter,
352 _x11_notify_handler_image,/* Raw image data is the same */
355 [CNP_ATOM_image_svg] = {
357 ELM_SEL_FORMAT_IMAGE,
358 _x11_image_converter,
360 _x11_notify_handler_image,/* Raw image data is the same */
363 [CNP_ATOM_image_xpm] = {
365 ELM_SEL_FORMAT_IMAGE,
366 _x11_image_converter,
368 _x11_notify_handler_image,/* Raw image data is the same */
371 [CNP_ATOM_image_tga] = {
373 ELM_SEL_FORMAT_IMAGE,
374 _x11_image_converter,
376 _x11_notify_handler_image,/* Raw image data is the same */
379 [CNP_ATOM_image_ppm] = {
380 "image/x-portable-pixmap",
381 ELM_SEL_FORMAT_IMAGE,
382 _x11_image_converter,
384 _x11_notify_handler_image,/* Raw image data is the same */
388 [CNP_ATOM_text_html_utf8] = {
389 "text/html;charset=utf-8",
391 _x11_general_converter,
393 _x11_notify_handler_html,
396 [CNP_ATOM_text_html] = {
399 _x11_general_converter,
401 _x11_notify_handler_html, // No encoding: Webkit only
405 [CNP_ATOM_UTF8STRING] = {
407 ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
410 _x11_notify_handler_text,
413 [CNP_ATOM_STRING] = {
415 ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
418 _x11_notify_handler_text,
421 [CNP_ATOM_COMPOUND_TEXT] = {
423 ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
426 _x11_notify_handler_text,
431 ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
434 _x11_notify_handler_text,
437 [CNP_ATOM_text_plain_utf8] = {
438 "text/plain;charset=utf-8",
439 ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
442 _x11_notify_handler_text,
445 [CNP_ATOM_text_plain] = {
447 ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
450 _x11_notify_handler_text,
455 static X11_Cnp_Selection _x11_selections[ELM_SEL_TYPE_CLIPBOARD + 1] = {
456 ARRAYINIT(ELM_SEL_TYPE_PRIMARY) {
458 .ecore_sel = ECORE_X_SELECTION_PRIMARY,
459 .set = ecore_x_selection_primary_set,
460 .clear = ecore_x_selection_primary_clear,
461 .request = ecore_x_selection_primary_request,
463 ARRAYINIT(ELM_SEL_TYPE_SECONDARY) {
464 .debug = "Secondary",
465 .ecore_sel = ECORE_X_SELECTION_SECONDARY,
466 .set = ecore_x_selection_secondary_set,
467 .clear = ecore_x_selection_secondary_clear,
468 .request = ecore_x_selection_secondary_request,
470 ARRAYINIT(ELM_SEL_TYPE_XDND) {
472 .ecore_sel = ECORE_X_SELECTION_XDND,
473 .request = ecore_x_selection_xdnd_request,
475 ARRAYINIT(ELM_SEL_TYPE_CLIPBOARD) {
476 .debug = "Clipboard",
477 .ecore_sel = ECORE_X_SELECTION_CLIPBOARD,
478 .set = ecore_x_selection_clipboard_set,
479 .clear = ecore_x_selection_clipboard_clear,
480 .request = ecore_x_selection_clipboard_request,
485 _x11_sel_obj_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
487 X11_Cnp_Selection *sel = data;
488 if (sel->widget == obj) sel->widget = NULL;
489 if (dragwidget == obj) dragwidget = NULL;
493 _x11_sel_obj_del2(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
495 X11_Cnp_Selection *sel = data;
496 if (sel->requestwidget == obj) sel->requestwidget = NULL;
500 _x11_selection_clear(void *udata __UNUSED__, int type __UNUSED__, void *event)
502 Ecore_X_Event_Selection_Clear *ev = event;
503 X11_Cnp_Selection *sel;
507 for (i = ELM_SEL_TYPE_PRIMARY; i <= ELM_SEL_TYPE_CLIPBOARD; i++)
509 if (_x11_selections[i].ecore_sel == ev->selection) break;
511 cnp_debug("selection %d clear\n", i);
512 /* Not me... Don't care */
513 if (i > ELM_SEL_TYPE_CLIPBOARD) return ECORE_CALLBACK_PASS_ON;
515 sel = _x11_selections + i;
516 if (sel->loss_cb) sel->loss_cb(sel->loss_data, i);
518 evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL,
519 _x11_sel_obj_del, sel);
520 if (sel->requestwidget)
521 evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL,
522 _x11_sel_obj_del2, sel);
524 sel->requestwidget = NULL;
525 sel->active = EINA_FALSE;
532 return ECORE_CALLBACK_PASS_ON;
536 * Response to a selection notify:
537 * - So we have asked for the selection list.
538 * - If it's the targets list, parse it, and fire of what we want,
539 * else it's the data we want.
542 _x11_selection_notify(void *udata __UNUSED__, int type __UNUSED__, void *event)
544 Ecore_X_Event_Selection_Notify *ev = event;
545 X11_Cnp_Selection *sel;
548 cnp_debug("selection notify callback: %d\n",ev->selection);
549 switch (ev->selection)
551 case ECORE_X_SELECTION_PRIMARY:
552 sel = _x11_selections + ELM_SEL_TYPE_PRIMARY;
554 case ECORE_X_SELECTION_SECONDARY:
555 sel = _x11_selections + ELM_SEL_TYPE_SECONDARY;
557 case ECORE_X_SELECTION_XDND:
558 sel = _x11_selections + ELM_SEL_TYPE_XDND;
560 case ECORE_X_SELECTION_CLIPBOARD:
561 sel = _x11_selections + ELM_SEL_TYPE_CLIPBOARD;
564 return ECORE_CALLBACK_PASS_ON;
566 cnp_debug("Target is %s\n", ev->target);
568 if (!elm_widget_focus_get(sel->requestwidget) &&
569 ((ev->selection == ECORE_X_SELECTION_SECONDARY) || (ev->selection == ECORE_X_SELECTION_CLIPBOARD)))
570 return ECORE_CALLBACK_PASS_ON;
572 for (i = 0; i < CNP_N_ATOMS; i++)
574 if (!strcmp(ev->target, _x11_atoms[i].name))
576 if (_x11_atoms[i].notify)
578 cnp_debug("Found something: %s\n", _x11_atoms[i].name);
579 _x11_atoms[i].notify(sel, ev);
581 else cnp_debug("Ignored: No handler!\n");
584 return ECORE_CALLBACK_PASS_ON;
587 static Elm_Sel_Format
588 _get_selection_type(void *data, int size)
590 if (size == sizeof(Elm_Sel_Type))
592 unsigned int seltype = *((unsigned int *)data);
593 if (seltype > ELM_SEL_TYPE_CLIPBOARD)
594 return ELM_SEL_FORMAT_NONE;
595 X11_Cnp_Selection *sel = _x11_selections + seltype;
597 (sel->format >= ELM_SEL_FORMAT_TARGETS) &&
598 (sel->format <= ELM_SEL_FORMAT_HTML))
601 return ELM_SEL_FORMAT_NONE;
605 _x11_targets_converter(char *target __UNUSED__, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize)
609 X11_Cnp_Selection *sel;
610 Elm_Sel_Format seltype;
612 if (!data_ret) return EINA_FALSE;
613 if (_get_selection_type(data, size) == ELM_SEL_FORMAT_NONE)
615 /* TODO : fallback into precise type */
616 seltype = ELM_SEL_FORMAT_TEXT;
620 sel = _x11_selections + *((int *)data);
621 seltype = sel->format;
624 for (i = 0, count = 0; i < CNP_N_ATOMS ; i++)
626 if (seltype & _x11_atoms[i].formats) count++;
628 aret = malloc(sizeof(Ecore_X_Atom) * count);
629 if (!aret) return EINA_FALSE;
630 for (i = 0, count = 0; i < CNP_N_ATOMS; i++)
632 if (seltype & _x11_atoms[i].formats)
633 aret[count ++] = _x11_atoms[i].atom;
637 if (typesize) *typesize = 32 /* urk */;
638 if (ttype) *ttype = ECORE_X_ATOM_ATOM;
639 if (size_ret) *size_ret = count;
644 _x11_image_converter(char *target __UNUSED__, void *data __UNUSED__, int size __UNUSED__, void **data_ret __UNUSED__, int *size_ret __UNUSED__, Ecore_X_Atom *ttype __UNUSED__, int *typesize __UNUSED__)
646 cnp_debug("Image converter called\n");
651 _x11_vcard_send(char *target __UNUSED__, void *data __UNUSED__, int size __UNUSED__, void **data_ret, int *size_ret, Ecore_X_Atom *ttype __UNUSED__, int *typesize __UNUSED__)
653 X11_Cnp_Selection *sel;
655 cnp_debug("Vcard send called\n");
656 sel = _x11_selections + *((int *)data);
657 if (data_ret) *data_ret = strdup(sel->selbuf);
658 if (size_ret) *size_ret = strlen(sel->selbuf);
665 _x11_is_uri_type_data(X11_Cnp_Selection *sel __UNUSED__, Ecore_X_Event_Selection_Notify *notify)
667 Ecore_X_Selection_Data *data;
671 cnp_debug("data->format is %d %p %p\n", data->format, notify, data);
672 if (data->content == ECORE_X_SELECTION_CONTENT_FILES) return EINA_TRUE;
673 p = (char *)data->data;
674 if (!p) return EINA_TRUE;
675 cnp_debug("Got %s\n", p);
676 if (strncmp(p, "file://", 7))
678 if (*p != '/') return EINA_FALSE;
686 * Callback to handle a targets response on a selection request:
687 * So pick the format we'd like; and then request it.
690 _x11_notify_handler_targets(X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
692 Ecore_X_Selection_Data_Targets *targets;
693 Ecore_X_Atom *atomlist;
696 targets = notify->data;
697 atomlist = (Ecore_X_Atom *)(targets->data.data);
698 for (j = (CNP_ATOM_LISTING_ATOMS + 1); j < CNP_N_ATOMS; j++)
700 cnp_debug("\t%s %d\n", _x11_atoms[j].name, _x11_atoms[j].atom);
701 if (!(_x11_atoms[j].formats & sel->requestformat)) continue;
702 for (i = 0; i < targets->data.length; i++)
704 if ((_x11_atoms[j].atom == atomlist[i]) && (_x11_atoms[j].notify))
708 if ((j == CNP_ATOM_text_uri) ||
709 (j == CNP_ATOM_text_urilist))
711 if (!_x11_is_uri_type_data(sel, notify)) continue;
715 cnp_debug("Atom %s matches\n", _x11_atoms[j].name);
720 cnp_debug("Couldn't find anything that matches\n");
721 return ECORE_CALLBACK_PASS_ON;
723 cnp_debug("Sending request for %s, xwin=%#llx\n",
724 _x11_atoms[j].name, (unsigned long long)sel->xwin);
725 sel->request(sel->xwin, _x11_atoms[j].name);
726 return ECORE_CALLBACK_PASS_ON;
730 _x11_response_handler_targets(X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
732 Ecore_X_Selection_Data_Targets *targets;
733 Ecore_X_Atom *atomlist;
736 targets = notify->data;
737 atomlist = (Ecore_X_Atom *)(targets->data.data);
739 for (j = (CNP_ATOM_LISTING_ATOMS + 1); j < CNP_N_ATOMS; j++)
741 if (!(_x11_atoms[j].formats & sel->requestformat)) continue;
742 for (i = 0; i < targets->data.length; i++)
744 if ((_x11_atoms[j].atom == atomlist[i]) &&
745 (_x11_atoms[j].response))
749 cnp_debug("No matching type found\n");
752 sel->request(sel->xwin, _x11_atoms[j].name);
757 _x11_notify_handler_text(X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
759 Ecore_X_Selection_Data *data;
764 if (sel == (_x11_selections + ELM_SEL_TYPE_XDND))
766 Elm_Selection_Data ddata;
768 cnp_debug("drag & drop\n");
769 /* FIXME: this needs to be generic: Used for all receives */
770 EINA_LIST_FOREACH(drops, l, dropable)
772 if (dropable->obj == sel->requestwidget) break;
777 ddata.x = savedtypes.x;
778 ddata.y = savedtypes.y;
779 ddata.format = ELM_SEL_FORMAT_TEXT;
780 ddata.data = data->data;
781 ddata.len = data->length;
782 ddata.action = sel->action;
783 dropable->dropcb(dropable->cbdata, dropable->obj, &ddata);
789 Elm_Selection_Data ddata;
791 ddata.x = ddata.y = 0;
792 ddata.format = ELM_SEL_FORMAT_TEXT;
793 ddata.data = data->data;
794 ddata.len = data->length;
795 ddata.action = sel->action;
796 sel->datacb(sel->udata, sel->widget, &ddata);
800 char *stripstr, *mkupstr;
802 stripstr = malloc(data->length + 1);
803 if (!stripstr) goto end;
804 strncpy(stripstr, (char *)data->data, data->length);
805 stripstr[data->length] = '\0';
806 cnp_debug("Notify handler text %d %d %p\n", data->format,
807 data->length, data->data);
808 mkupstr = _elm_util_text_to_mkup((const char *)stripstr);
809 cnp_debug("String is %s (from %s)\n", stripstr, data->data);
810 /* TODO BUG: should never NEVER assume it's an elm_entry! */
811 //_elm_entry_entry_paste(sel->requestwidget, mkupstr); // TIZEN ONLY
814 _entry_insert_filter(sel->requestwidget, mkupstr);
816 _entry_insert_filter(sel->requestwidget, stripstr);
823 if (sel == (_x11_selections + ELM_SEL_TYPE_XDND))
824 ecore_x_dnd_send_finished();
829 * So someone is pasting an image into my entry or widget...
832 _x11_notify_handler_uri(X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
834 Ecore_X_Selection_Data *data;
835 Ecore_X_Selection_Data_Files *files;
836 char *p, *s, *stripstr = NULL;
839 cnp_debug("data->format is %d %p %p\n", data->format, notify, data);
840 if (data->content == ECORE_X_SELECTION_CONTENT_FILES)
844 cnp_debug("got a files list\n");
845 files = notify->data;
847 if (files->num_files > 1)
849 // Don't handle many items <- this makes mr bigglesworth sad :(
850 cnp_debug("more then one file: Bailing\n");
853 stripstr = p = strdup(files->files[0]);
855 for (i = 0; i < files->num_files ; i++)
858 if (strncmp(p, "file://", 7) && (p[0] != '/')) continue;
859 if (!strncmp(p, "file://", 7)) p += 7;
860 len += strlen(p) + 1;
865 s = stripstr = malloc(len + 1);
866 for (i = 0; i < files->num_files ; i++)
869 if ((strncmp(p, "file://", 7)) && (p[0] != '/')) continue;
870 if (!strncmp(p, "file://", 7)) p += 7;
873 if (i < (files->num_files - 1))
889 p = (char *)data->data;
890 if ((!strncmp(p, "file://", 7)) || (p[0] == '/'))
892 int len = data->length;
893 if (!strncmp(p, "file://", 7))
898 stripstr = malloc(len + 1);
899 if (!stripstr) return 0;
900 memcpy(stripstr, p, len);
906 cnp_debug("Couldn't find a file\n");
909 if (savedtypes.imgfile) free(savedtypes.imgfile);
910 if (savedtypes.textreq)
912 savedtypes.textreq = 0;
913 savedtypes.imgfile = stripstr;
917 savedtypes.imgfile = NULL;
918 _pasteimage_append(stripstr, sel->requestwidget);
925 * Just receieved an vcard, either through cut and paste, or dnd.
928 _x11_vcard_receive(X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
932 Ecore_X_Selection_Data *data;
935 cnp_debug("vcard receive\n");
936 if (sel == (_x11_selections + ELM_SEL_TYPE_XDND))
938 Elm_Selection_Data ddata;
940 cnp_debug("drag & drop\n");
941 /* FIXME: this needs to be generic: Used for all receives */
942 EINA_LIST_FOREACH(drops, l, dropable)
944 if (dropable->obj == sel->requestwidget) break;
948 cnp_debug("Unable to find drop object");
949 ecore_x_dnd_send_finished();
952 dropable = eina_list_data_get(l);
953 ddata.x = savedtypes.x;
954 ddata.y = savedtypes.y;
955 ddata.format = ELM_SEL_FORMAT_VCARD;
956 ddata.data = data->data;
957 ddata.len = data->length;
958 ddata.action = sel->action;
959 dropable->dropcb(dropable->cbdata, dropable->obj, &ddata);
960 ecore_x_dnd_send_finished();
962 else if (sel->datacb)
964 Elm_Selection_Data ddata;
965 ddata.x = ddata.y = 0;
966 ddata.format = ELM_SEL_FORMAT_VCARD;
967 ddata.data = data->data;
968 ddata.len = data->length;
969 ddata.action = sel->action;
970 sel->datacb(sel->udata, sel->widget, &ddata);
972 else cnp_debug("Paste request\n");
977 _x11_notify_handler_image(X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
979 Ecore_X_Selection_Data *data;
982 cnp_debug("got a image file!\n");
985 cnp_debug("Size if %d\n", data->length);
988 Elm_Selection_Data ddata;
990 ddata.x = ddata.y = 0;
991 ddata.format = ELM_SEL_FORMAT_IMAGE;
992 ddata.data = data->data;
993 ddata.len = data->length;
994 ddata.action = sel->action;
995 sel->datacb(sel->udata, sel->widget, &ddata);
998 /* generate tmp name */
999 tmp = _tempfile_new(data->length);
1001 memcpy(tmp->map, data->data, data->length);
1002 munmap(tmp->map, data->length);
1003 /* FIXME: Add to paste image data to clean up */
1004 _pasteimage_append(tmp->filename, sel->requestwidget);
1011 _x11_notify_handler_edje(X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
1013 Ecore_X_Selection_Data *data;
1015 data = notify->data;
1019 Elm_Selection_Data ddata;
1020 ddata.x = ddata.y = 0;
1021 ddata.format = ELM_SEL_FORMAT_MARKUP;
1022 ddata.data = data->data;
1023 ddata.len = data->length;
1024 sel->datacb(sel->udata, sel->widget, &ddata);
1029 stripstr = malloc(data->length + 1);
1030 if (!stripstr) return 0;
1031 strncpy(stripstr, (char *)data->data, data->length);
1032 stripstr[data->length] = '\0';
1034 _entry_insert_filter(sel->requestwidget, stripstr);
1035 cnp_debug("String is %s (%d bytes)\n", stripstr, data->length);
1044 * Warning: Generic text/html can';t handle it sanely.
1045 * Firefox sends ucs2 (i think).
1046 * chrome sends utf8... blerg
1050 _x11_notify_handler_html(X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
1052 Ecore_X_Selection_Data *data;
1054 cnp_debug("Got some HTML: Checking encoding is useful\n");
1055 data = notify->data;
1056 char *stripstr = malloc(data->length + 1);
1057 if (!stripstr) return 0;
1058 strncpy(stripstr, (char *)data->data, data->length);
1059 stripstr[data->length] = '\0';
1063 Elm_Selection_Data ddata;
1064 ddata.x = ddata.y = 0;
1065 ddata.format = ELM_SEL_FORMAT_HTML;
1066 ddata.data = stripstr;
1067 ddata.len = data->length;
1068 ddata.action = ELM_XDND_ACTION_UNKNOWN;
1069 sel->datacb(sel->udata, sel->widget, &ddata);
1074 cnp_debug("String is %s (%d bytes)\n", stripstr, data->length);
1075 // TODO BUG: should never NEVER assume it's an elm_entry!
1076 _elm_entry_entry_paste(sel->requestwidget, stripstr);
1083 _x11_text_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize)
1085 X11_Cnp_Selection *sel;
1087 cnp_debug("text converter\n");
1088 if (_get_selection_type(data, size) == ELM_SEL_FORMAT_NONE)
1092 *data_ret = malloc(size * sizeof(char) + 1);
1093 if (!*data_ret) return EINA_FALSE;
1094 memcpy(*data_ret, data, size);
1095 ((char**)(data_ret))[0][size] = 0;
1097 if (size_ret) *size_ret = size;
1100 sel = _x11_selections + *((int *)data);
1101 if (!sel->active) return EINA_TRUE;
1103 if ((sel->format & ELM_SEL_FORMAT_MARKUP) ||
1104 (sel->format & ELM_SEL_FORMAT_HTML))
1106 *data_ret = _elm_util_mkup_to_text(sel->selbuf);
1107 if (size_ret && *data_ret) *size_ret = strlen(*data_ret);
1109 else if (sel->format & ELM_SEL_FORMAT_TEXT)
1111 ecore_x_selection_converter_text(target, sel->selbuf,
1112 strlen(sel->selbuf),
1116 else if (sel->format & ELM_SEL_FORMAT_IMAGE)
1118 cnp_debug("Image %s\n", evas_object_type_get(sel->widget));
1119 cnp_debug("Elm type: %s\n", elm_object_widget_type_get(sel->widget));
1120 evas_object_image_file_get(elm_photocam_internal_image_get(sel->widget),
1121 (const char **)data_ret, NULL);
1122 if (!*data_ret) *data_ret = strdup("No file");
1123 else *data_ret = strdup(*data_ret);
1124 *size_ret = strlen(*data_ret);
1130 _x11_general_converter(char *target __UNUSED__, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype __UNUSED__, int *typesize __UNUSED__)
1132 if (_get_selection_type(data, size) == ELM_SEL_FORMAT_NONE)
1136 *data_ret = malloc(size * sizeof(char) + 1);
1137 if (!*data_ret) return EINA_FALSE;
1138 memcpy(*data_ret, data, size);
1139 ((char**)(data_ret))[0][size] = 0;
1141 if (size_ret) *size_ret = size;
1145 X11_Cnp_Selection *sel = _x11_selections + *((int *)data);
1148 if (data_ret) *data_ret = strdup(sel->selbuf);
1149 if (size_ret) *size_ret = strlen(sel->selbuf);
1153 if (data_ret) *data_ret = NULL;
1154 if (size_ret) *size_ret = 0;
1161 _x11_dropable_find(Ecore_X_Window win)
1166 if (!drops) return NULL;
1167 EINA_LIST_FOREACH(drops, l, dropable)
1169 if (_x11_elm_widget_xwin_get(dropable->obj) == win) return dropable;
1175 _x11_dropable_geom_find(Ecore_X_Window win, Evas_Coord px, Evas_Coord py)
1177 Eina_List *itr, *top_objects_list = NULL;
1179 Evas_Object *top_obj;
1180 Dropable *dropable = NULL;
1182 if (!drops) return NULL;
1183 /* Find the Evas connected to the window */
1184 EINA_LIST_FOREACH(drops, itr, dropable)
1186 if (_x11_elm_widget_xwin_get(dropable->obj) == win)
1188 evas = evas_object_evas_get(dropable->obj);
1192 if (!evas) return NULL;
1194 /* We retrieve the (non-smart) objects pointed by (px, py) */
1195 top_objects_list = evas_tree_objects_at_xy_get(evas, NULL, px, py);
1196 /* We walk on this list from the last because if the list contains more than one
1197 * element, all but the last will repeat events. The last one can repeat events
1198 * or not. Anyway, this last one is the first that has to be taken into account
1199 * for the determination of the drop target.
1201 EINA_LIST_REVERSE_FOREACH(top_objects_list, itr, top_obj)
1203 Evas_Object *object = top_obj;
1204 /* We search for the dropable data into the object. If not found, we search into its parent.
1205 * For example, if a button is a drop target, the first object will be an (internal) image.
1206 * The drop target is attached to the button, i.e to image's parent. That's why we need to
1207 * walk on the parents until NULL.
1208 * If we find this dropable data, we found our drop target.
1212 dropable = evas_object_data_get(object, "dropable");
1216 object = evas_object_smart_parent_get(object);
1220 eina_list_free(top_objects_list);
1225 _x11_dropable_coords_adjust(Dropable *dropable, Evas_Coord *x, Evas_Coord *y)
1230 ee = ecore_evas_ecore_evas_get(evas_object_evas_get(dropable->obj));
1231 ecore_evas_geometry_get(ee, &ex, &ey, NULL, NULL);
1237 _x11_dropable_all_set(Ecore_X_Window win, Evas_Coord x, Evas_Coord y, Eina_Bool set)
1241 EINA_LIST_FOREACH(drops, l, dropable)
1243 if (_x11_elm_widget_xwin_get(dropable->obj) == win)
1245 dropable->last.x = x;
1246 dropable->last.y = y;
1247 dropable->last.in = set;
1253 _x11_dnd_enter(void *data __UNUSED__, int etype __UNUSED__, void *ev)
1255 Ecore_X_Event_Xdnd_Enter *enter = ev;
1259 if (!enter) return EINA_TRUE;
1260 dropable = _x11_dropable_find(enter->win);
1263 cnp_debug("Enter %x\n", enter->win);
1264 _x11_dropable_all_set(enter->win, 0, 0, EINA_FALSE);
1267 cnp_debug("enter types=%p (%d)\n", enter->types, enter->num_types);
1268 if ((!enter->num_types) || (!enter->types)) return EINA_TRUE;
1270 cnp_debug("Types\n");
1271 savedtypes.ntypes = enter->num_types;
1272 if (savedtypes.types) free(savedtypes.types);
1273 savedtypes.types = malloc(sizeof(char *) * enter->num_types);
1274 if (!savedtypes.types) return EINA_FALSE;
1276 for (i = 0; i < enter->num_types; i++)
1278 savedtypes.types[i] = eina_stringshare_add(enter->types[i]);
1279 cnp_debug("Type is %s %p %p\n", enter->types[i],
1280 savedtypes.types[i], text_uri);
1281 if (savedtypes.types[i] == text_uri)
1283 /* Request it, so we know what it is */
1284 cnp_debug("Sending uri request\n");
1285 savedtypes.textreq = 1;
1286 if (savedtypes.imgfile) free(savedtypes.imgfile);
1287 savedtypes.imgfile = NULL;
1288 ecore_x_selection_xdnd_request(enter->win, text_uri);
1292 /* FIXME: Find an object and make it current */
1297 _x11_dnd_dropable_handle(Dropable *dropable, Evas_Coord x, Evas_Coord y, Eina_Bool have_obj, Elm_Xdnd_Action action)
1299 Dropable *dropable_last = NULL;
1301 if (dropable->last.in)
1302 dropable_last = _x11_dropable_geom_find
1303 (_x11_elm_widget_xwin_get(dropable->obj),
1304 dropable->last.x, dropable->last.y);
1305 if ((have_obj) && (dropable_last == dropable)) // same
1307 cnp_debug("same obj dropable %p\n", dropable);
1308 if (dropable->poscb)
1309 dropable->poscb(dropable->posdata, dropable->obj, x, y, action);
1311 else if ((have_obj) && (!dropable_last)) // enter new obj
1313 cnp_debug("enter %p\n", dropable->obj);
1314 if (dropable->entercb)
1315 dropable->entercb(dropable->enterdata, dropable->obj);
1316 if (dropable->poscb)
1317 dropable->poscb(dropable->posdata, dropable->obj, x, y, action);
1319 else if ((!have_obj) && (dropable_last)) // leave last obj
1321 cnp_debug("leave %p\n", dropable_last->obj);
1322 if (dropable->leavecb)
1323 dropable->leavecb(dropable->leavedata, dropable->obj);
1325 else if (have_obj) // leave last obj and enter new one
1327 cnp_debug("enter %p\n", dropable->obj);
1328 if (dropable->entercb)
1329 dropable->entercb(dropable->enterdata, dropable->obj);
1332 dropable = dropable_last;
1333 if (dropable->leavecb)
1334 dropable->leavecb(dropable->leavedata, dropable->obj);
1335 cnp_debug("leave %p\n", dropable->obj);
1340 static Elm_Xdnd_Action
1341 _x11_dnd_action_map(Ecore_X_Atom action)
1343 Elm_Xdnd_Action act = ELM_XDND_ACTION_UNKNOWN;
1345 if (action == ECORE_X_ATOM_XDND_ACTION_COPY)
1346 act = ELM_XDND_ACTION_COPY;
1347 else if (action == ECORE_X_ATOM_XDND_ACTION_MOVE)
1348 act = ELM_XDND_ACTION_MOVE;
1349 else if (action == ECORE_X_ATOM_XDND_ACTION_PRIVATE)
1350 act = ELM_XDND_ACTION_PRIVATE;
1351 else if (action == ECORE_X_ATOM_XDND_ACTION_ASK)
1352 act = ELM_XDND_ACTION_ASK;
1353 else if (action == ECORE_X_ATOM_XDND_ACTION_LIST)
1354 act = ELM_XDND_ACTION_LIST;
1355 else if (action == ECORE_X_ATOM_XDND_ACTION_LINK)
1356 act = ELM_XDND_ACTION_LINK;
1357 else if (action == ECORE_X_ATOM_XDND_ACTION_DESCRIPTION)
1358 act = ELM_XDND_ACTION_DESCRIPTION;
1363 _x11_dnd_action_rev_map(Elm_Xdnd_Action action)
1365 Ecore_X_Atom act = ECORE_X_ATOM_XDND_ACTION_MOVE;
1367 if (action == ELM_XDND_ACTION_COPY)
1368 act = ECORE_X_ATOM_XDND_ACTION_COPY;
1369 else if (action == ELM_XDND_ACTION_MOVE)
1370 act = ECORE_X_ATOM_XDND_ACTION_MOVE;
1371 else if (action == ELM_XDND_ACTION_PRIVATE)
1372 act = ECORE_X_ATOM_XDND_ACTION_PRIVATE;
1373 else if (action == ELM_XDND_ACTION_ASK)
1374 act = ECORE_X_ATOM_XDND_ACTION_ASK;
1375 else if (action == ELM_XDND_ACTION_LIST)
1376 act = ECORE_X_ATOM_XDND_ACTION_LIST;
1377 else if (action == ELM_XDND_ACTION_LINK)
1378 act = ECORE_X_ATOM_XDND_ACTION_LINK;
1379 else if (action == ELM_XDND_ACTION_DESCRIPTION)
1380 act = ECORE_X_ATOM_XDND_ACTION_DESCRIPTION;
1385 _x11_dnd_position(void *data __UNUSED__, int etype __UNUSED__, void *ev)
1387 Ecore_X_Event_Xdnd_Position *pos = ev;
1388 Ecore_X_Rectangle rect;
1389 Dropable *dropable, *dropable_old;
1390 Elm_Xdnd_Action act;
1392 /* Need to send a status back */
1393 /* FIXME: Should check I can drop here */
1394 /* FIXME: Should highlight widget */
1395 dropable_old = dropable = _x11_dropable_find(pos->win);
1398 Evas_Coord x, y, ox = 0, oy = 0, ow = 0, oh = 0;
1400 x = pos->position.x;
1401 y = pos->position.y;
1402 _x11_dropable_coords_adjust(dropable, &x, &y);
1403 dropable = _x11_dropable_geom_find(pos->win, x, y);
1404 act = _x11_dnd_action_map(pos->action);
1407 evas_object_geometry_get(dropable->obj, &ox, &oy, &ow, &oh);
1408 rect.x = pos->position.x - x + ox;
1409 rect.y = pos->position.y - y + oy;
1412 ecore_x_dnd_send_status(EINA_TRUE, EINA_FALSE, rect, pos->action);
1413 cnp_debug("dnd position %i %i %p\n", x - ox, y - oy, dropable);
1414 _x11_dnd_dropable_handle(dropable, x - ox, y - oy, EINA_TRUE,
1416 // CCCCCCC: call dnd exit on last obj if obj != last
1417 // CCCCCCC: call drop position on obj
1418 _x11_dropable_all_set(pos->win, x, y, EINA_TRUE);
1422 ecore_x_dnd_send_status(EINA_FALSE, EINA_FALSE, rect, pos->action);
1423 cnp_debug("dnd position (%d, %d) not in obj\n", x, y);
1424 _x11_dnd_dropable_handle(dropable_old, 0, 0, EINA_FALSE,
1426 // CCCCCCC: call dnd exit on last obj
1427 _x11_dropable_all_set(pos->win, x, y, EINA_TRUE);
1432 ecore_x_dnd_send_status(EINA_FALSE, EINA_FALSE, rect, pos->action);
1438 _x11_dnd_leave(void *data __UNUSED__, int etype __UNUSED__, void *ev)
1440 Ecore_X_Event_Xdnd_Leave *leave = ev;
1443 dropable = _x11_dropable_find(leave->win);
1446 cnp_debug("Leave %x\n", leave->win);
1447 _x11_dnd_dropable_handle(dropable, 0, 0, EINA_FALSE, ELM_XDND_ACTION_UNKNOWN);
1448 _x11_dropable_all_set(leave->win, 0, 0, EINA_FALSE);
1449 // CCCCCCC: call dnd exit on last obj if there was one
1451 // leave->win leave->source
1456 _x11_dnd_drop(void *data __UNUSED__, int etype __UNUSED__, void *ev)
1458 Ecore_X_Event_Xdnd_Drop *drop;
1460 Elm_Selection_Data ddata;
1461 Evas_Coord x = 0, y = 0;
1462 Elm_Xdnd_Action act = ELM_XDND_ACTION_UNKNOWN;
1467 cnp_debug("drops %p (%d)\n", drops, eina_list_count(drops));
1468 if (!(dropable = _x11_dropable_find(drop->win))) return EINA_TRUE;
1470 /* Calculate real (widget relative) position */
1471 // - window position
1472 // - widget position
1473 savedtypes.x = drop->position.x;
1474 savedtypes.y = drop->position.y;
1475 _x11_dropable_coords_adjust(dropable, &savedtypes.x, &savedtypes.y);
1477 cnp_debug("Drop position is %d,%d\n", savedtypes.x, savedtypes.y);
1479 dropable = _x11_dropable_geom_find(drop->win, savedtypes.x, savedtypes.y);
1480 if (!dropable) return EINA_TRUE; /* didn't find one */
1482 evas_object_geometry_get(dropable->obj, &x, &y, NULL, NULL);
1486 /* Find our type from the previous list */
1487 for (i = 0; i < CNP_N_ATOMS; i++)
1489 for (j = 0; j < savedtypes.ntypes; j++)
1491 if (!strcmp(savedtypes.types[j], _x11_atoms[i].name)) goto found;
1495 cnp_debug("Didn't find a target\n");
1499 cnp_debug("Found a target we'd like: %s\n", _x11_atoms[i].name);
1500 cnp_debug("0x%x\n", drop->win);
1502 act = _x11_dnd_action_map(drop->action);
1504 if (i == CNP_ATOM_text_urilist)
1506 cnp_debug("We found a URI... (%scached) %s\n",
1507 savedtypes.imgfile ? "" : "not ",
1508 savedtypes.imgfile);
1509 if (savedtypes.imgfile)
1511 ddata.x = savedtypes.x;
1512 ddata.y = savedtypes.y;
1515 /* If it's markup that also supports images */
1516 if ((dropable->types & ELM_SEL_FORMAT_MARKUP) &&
1517 (dropable->types & ELM_SEL_FORMAT_IMAGE))
1519 ddata.format = ELM_SEL_FORMAT_MARKUP;
1520 ddata.data = savedtypes.imgfile;
1521 cnp_debug("Insert %s\n", (char *)ddata.data);
1522 if (dropable->dropcb) dropable->dropcb(dropable->cbdata, dropable->obj, &ddata);
1523 ecore_x_dnd_send_finished();
1524 if (savedtypes.imgfile) free(savedtypes.imgfile);
1525 savedtypes.imgfile = NULL;
1529 else if (dropable->types & ELM_SEL_FORMAT_IMAGE)
1531 cnp_debug("Doing image insert (%s)\n", savedtypes.imgfile);
1532 ddata.format = ELM_SEL_FORMAT_IMAGE;
1533 ddata.data = (char *)savedtypes.imgfile;
1534 dropable->dropcb(dropable->cbdata, dropable->obj, &ddata);
1535 ecore_x_dnd_send_finished();
1536 if (savedtypes.imgfile) free(savedtypes.imgfile);
1537 savedtypes.imgfile = NULL;
1543 cnp_debug("Item doesn't support images... passing\n");
1547 else if (savedtypes.textreq)
1549 /* Already asked: Pretend we asked now, and paste immediately when
1551 cnp_debug("textreq <%d>\n", __LINE__);
1552 ddata.x = savedtypes.x;
1553 ddata.y = savedtypes.y;
1554 ddata.data = _x11_selections[ELM_SEL_TYPE_PRIMARY].selbuf;
1555 dropable->dropcb(dropable->cbdata, dropable->obj, &ddata);
1556 ecore_x_dnd_send_finished();
1561 cnp_debug("doing a request then\n");
1562 _x11_selections[ELM_SEL_TYPE_XDND].xwin = drop->win;
1563 _x11_selections[ELM_SEL_TYPE_XDND].requestwidget = dropable->obj;
1564 _x11_selections[ELM_SEL_TYPE_XDND].requestformat = ELM_SEL_FORMAT_MARKUP;
1565 _x11_selections[ELM_SEL_TYPE_XDND].active = EINA_TRUE;
1566 _x11_selections[ELM_SEL_TYPE_XDND].action = act;
1568 ecore_x_selection_xdnd_request(drop->win, _x11_atoms[i].name);
1573 _x11_dnd_status(void *data __UNUSED__, int etype __UNUSED__, void *ev)
1575 Ecore_X_Event_Xdnd_Status *status = ev;
1576 doaccept = EINA_FALSE;
1578 /* Only thing we care about: will accept */
1579 if ((status) && (status->will_accept))
1581 cnp_debug("Will accept\n");
1582 doaccept = EINA_TRUE;
1587 cnp_debug("Won't accept accept\n");
1590 dragacceptcb(dragacceptdata, _x11_selections[ELM_SEL_TYPE_XDND].widget,
1596 _drag_cancel_animate(void *data __UNUSED__, double pos)
1597 { /* Animation to "move back" drag-window */
1600 evas_object_del(data);
1601 return ECORE_CALLBACK_CANCEL;
1606 x = dragwin_x_end - (pos * (dragwin_x_end - dragwin_x_start));
1607 y = dragwin_y_end - (pos * (dragwin_y_end - dragwin_y_start));
1608 evas_object_move(data, x, y);
1611 return ECORE_CALLBACK_RENEW;
1615 _x11_drag_mouse_up(void *data, int etype __UNUSED__, void *event)
1617 Ecore_X_Window xwin = (Ecore_X_Window)(long)data;
1618 Ecore_Event_Mouse_Button *ev = event;
1620 if ((ev->buttons == 1) &&
1621 (ev->event_window == xwin))
1623 Eina_Bool have_drops = EINA_FALSE;
1627 ecore_x_pointer_ungrab();
1630 ecore_event_handler_del(handler_up);
1635 ecore_event_handler_del(handler_status);
1636 handler_status = NULL;
1638 ecore_x_dnd_self_drop();
1640 cnp_debug("mouse up, xwin=%#llx\n", (unsigned long long)xwin);
1642 EINA_LIST_FOREACH(drops, l, dropable)
1644 if (xwin == _x11_elm_widget_xwin_get(dropable->obj))
1646 have_drops = EINA_TRUE;
1650 if (!have_drops) ecore_x_dnd_aware_set(xwin, EINA_FALSE);
1651 if (dragdonecb) dragdonecb(dragdonedata, dragwidget);
1655 { /* Commit animation when drag cancelled */
1656 /* Record final position of dragwin, then do animation */
1657 ecore_animator_timeline_add(0.3,
1658 _drag_cancel_animate, dragwin);
1661 { /* No animation drop was committed */
1662 evas_object_del(dragwin);
1665 dragwin = NULL; /* if not freed here, free in end of anim */
1669 dragacceptcb = NULL;
1672 doaccept = EINA_FALSE;
1673 /* moved to _drag_cancel_animate
1676 evas_object_del(dragwin);
1685 _x11_drag_move(void *data __UNUSED__, Ecore_X_Xdnd_Position *pos)
1687 evas_object_move(dragwin,
1688 pos->position.x - _dragx, pos->position.y - _dragy);
1689 dragwin_x_end = pos->position.x - _dragx;
1690 dragwin_y_end = pos->position.y - _dragy;
1691 cnp_debug("dragevas: %p -> %p\n",
1693 evas_object_evas_get(dragwidget));
1695 dragposcb(dragposdata, dragwidget, pos->position.x, pos->position.y,
1699 static Ecore_X_Window
1700 _x11_elm_widget_xwin_get(const Evas_Object *obj)
1703 Ecore_X_Window xwin = 0;
1705 top = elm_widget_top_get(obj);
1706 if (!top) top = elm_widget_top_get(elm_widget_parent_widget_get(obj));
1707 if (top) xwin = elm_win_xwindow_get(top);
1711 Evas *evas = evas_object_evas_get(obj);
1712 if (!evas) return 0;
1713 ee = ecore_evas_ecore_evas_get(evas);
1715 xwin = _elm_ee_xwin_get(ee);
1721 _x11_elm_cnp_init(void)
1724 static int _init_count = 0;
1726 if (_init_count > 0) return EINA_TRUE;
1728 for (i = 0; i < CNP_N_ATOMS; i++)
1730 _x11_atoms[i].atom = ecore_x_atom_get(_x11_atoms[i].name);
1731 ecore_x_selection_converter_atom_add
1732 (_x11_atoms[i].atom, _x11_atoms[i].converter);
1734 //XXX delete handlers?
1735 ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, _x11_selection_clear, NULL);
1736 ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, _x11_selection_notify, NULL);
1741 _x11_elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, const void *selbuf, size_t buflen)
1743 Ecore_X_Window xwin = _x11_elm_widget_xwin_get(obj);
1744 X11_Cnp_Selection *sel;
1746 _x11_elm_cnp_init();
1747 if ((!selbuf) && (format != ELM_SEL_FORMAT_IMAGE))
1748 return elm_object_cnp_selection_clear(obj, selection);
1750 sel = _x11_selections + selection;
1751 if (sel->loss_cb) sel->loss_cb(sel->loss_data, selection);
1753 evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL,
1754 _x11_sel_obj_del, sel);
1757 sel->active = EINA_TRUE;
1760 if (sel->set) sel->set(xwin, &selection, sizeof(Elm_Sel_Type));
1761 sel->format = format;
1762 sel->loss_cb = NULL;
1763 sel->loss_data = NULL;
1765 evas_object_event_callback_add
1766 (sel->widget, EVAS_CALLBACK_DEL, _x11_sel_obj_del, sel);
1770 if (format == ELM_SEL_FORMAT_IMAGE)
1772 // selbuf is actual image data, not text/string
1773 sel->selbuf = malloc(buflen + 1);
1776 elm_object_cnp_selection_clear(obj, selection);
1779 memcpy(sel->selbuf, selbuf, buflen);
1780 sel->selbuf[buflen] = 0;
1783 sel->selbuf = strdup((char*)selbuf);
1792 _x11_elm_cnp_selection_loss_callback_set(Evas_Object *obj __UNUSED__, Elm_Sel_Type selection, Elm_Selection_Loss_Cb func, const void *data)
1794 X11_Cnp_Selection *sel;
1796 _x11_elm_cnp_init();
1797 sel = _x11_selections + selection;
1798 sel->loss_cb = func;
1799 sel->loss_data = (void *)data;
1803 _x11_elm_object_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type selection)
1805 X11_Cnp_Selection *sel;
1807 _x11_elm_cnp_init();
1809 sel = _x11_selections + selection;
1811 /* No longer this selection: Consider it gone! */
1812 if ((!sel->active) || (sel->widget != obj)) return EINA_TRUE;
1815 evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL,
1816 _x11_sel_obj_del, sel);
1817 if (sel->requestwidget)
1818 evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL,
1819 _x11_sel_obj_del2, sel);
1821 sel->requestwidget = NULL;
1822 sel->loss_cb = NULL;
1823 sel->loss_data = NULL;
1825 sel->active = EINA_FALSE;
1837 _x11_elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection,
1838 Elm_Sel_Format format, Elm_Drop_Cb datacb,
1841 Ecore_X_Window xwin = _x11_elm_widget_xwin_get(obj);
1842 X11_Cnp_Selection *sel;
1844 _x11_elm_cnp_init();
1846 sel = _x11_selections + selection;
1848 if (sel->requestwidget)
1849 evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL,
1850 _x11_sel_obj_del2, sel);
1851 sel->requestwidget = NULL;
1853 sel->requestformat = format;
1854 sel->requestwidget = obj;
1856 sel->request(xwin, ECORE_X_SELECTION_TARGET_TARGETS);
1857 sel->datacb = datacb;
1860 evas_object_event_callback_add
1861 (sel->requestwidget, EVAS_CALLBACK_DEL, _x11_sel_obj_del2, sel);
1867 _x11_elm_drop_target_add(Evas_Object *obj, Elm_Sel_Format format,
1868 Elm_Drag_State entercb, void *enterdata,
1869 Elm_Drag_State leavecb, void *leavedata,
1870 Elm_Drag_Pos poscb, void *posdata,
1871 Elm_Drop_Cb dropcb, void *cbdata)
1873 Dropable *drop, *dropable;
1874 Ecore_X_Window xwin = _x11_elm_widget_xwin_get(obj);
1875 Eina_List *item, *l;
1877 Eina_Bool have_drops = EINA_FALSE;
1879 _x11_elm_cnp_init();
1881 /* TODO: check if obj is already a drop target. Do not add twice! */
1883 /* Is this the first? */
1884 EINA_LIST_FOREACH(drops, l, dropable)
1886 if (xwin == _x11_elm_widget_xwin_get(dropable->obj))
1888 have_drops = EINA_TRUE;
1892 first = (!drops) ? 1 : 0;
1894 EINA_LIST_FOREACH(drops, item, drop)
1896 if (drop->obj == obj)
1898 /* Update: Not a new one */
1899 drop->dropcb = dropcb;
1900 drop->cbdata = cbdata;
1901 drop->types = format;
1906 /* Create new drop */
1907 drop = calloc(1, sizeof(Dropable));
1908 if (!drop) return EINA_FALSE;
1909 /* FIXME: Check for eina's deranged error method */
1910 drops = eina_list_append(drops, drop);
1912 if (!drops/* || or other error */)
1917 drop->entercb = entercb;
1918 drop->enterdata = enterdata;
1919 drop->leavecb = leavecb;
1920 drop->leavedata = leavedata;
1921 drop->poscb = poscb;
1922 drop->posdata = posdata;
1923 drop->dropcb = dropcb;
1924 drop->cbdata = cbdata;
1925 drop->types = format;
1928 evas_object_data_set(obj, "dropable", drop);
1929 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
1930 /* I love C and varargs */
1931 (Evas_Object_Event_Cb)elm_drop_target_del,
1933 if (!have_drops) ecore_x_dnd_aware_set(xwin, EINA_TRUE);
1935 /* TODO BUG: should handle dnd-aware per window, not just the first
1936 * window that requested it! */
1937 /* If not the first: We're done */
1938 if (!first) return EINA_TRUE;
1941 cnp_debug("Adding drop target calls xwin=%#llx\n", (unsigned long long)xwin);
1942 handler_enter = ecore_event_handler_add(ECORE_X_EVENT_XDND_ENTER,
1943 _x11_dnd_enter, NULL);
1944 handler_leave = ecore_event_handler_add(ECORE_X_EVENT_XDND_LEAVE,
1945 _x11_dnd_leave, NULL);
1946 handler_pos = ecore_event_handler_add(ECORE_X_EVENT_XDND_POSITION,
1947 _x11_dnd_position, NULL);
1948 handler_drop = ecore_event_handler_add(ECORE_X_EVENT_XDND_DROP,
1949 _x11_dnd_drop, NULL);
1954 _x11_elm_drop_target_del(Evas_Object *obj)
1958 Ecore_X_Window xwin;
1959 Eina_Bool have_drops = EINA_FALSE;
1961 _x11_elm_cnp_init();
1963 dropable = evas_object_data_get(obj, "dropable");
1966 drops = eina_list_remove(drops, dropable);
1967 evas_object_data_del(obj, "dropable");
1971 else return EINA_FALSE;
1973 evas_object_event_callback_del(obj, EVAS_CALLBACK_FREE,
1974 (Evas_Object_Event_Cb)elm_drop_target_del);
1976 /* TODO BUG: we should handle dnd-aware per window, not just the last that reelased it */
1978 /* If still drops there: All fine.. continue */
1979 if (drops) return EINA_TRUE;
1981 cnp_debug("Disabling DND\n");
1982 xwin = _x11_elm_widget_xwin_get(obj);
1983 EINA_LIST_FOREACH(drops, l, dropable)
1985 if (xwin == _x11_elm_widget_xwin_get(dropable->obj))
1987 have_drops = EINA_TRUE;
1991 if (!have_drops) ecore_x_dnd_aware_set(xwin, EINA_FALSE);
1997 ecore_event_handler_del(handler_pos);
2002 ecore_event_handler_del(handler_drop);
2003 handler_drop = NULL;
2007 ecore_event_handler_del(handler_enter);
2008 handler_enter = NULL;
2012 ecore_event_handler_del(handler_leave);
2013 handler_leave = NULL;
2017 if (savedtypes.imgfile) free(savedtypes.imgfile);
2018 savedtypes.imgfile = NULL;
2024 _x11_drag_target_del(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *info __UNUSED__)
2026 X11_Cnp_Selection *sel = _x11_selections + ELM_SEL_TYPE_XDND;
2028 if (dragwidget == obj)
2036 _x11_elm_drag_start(Evas_Object *obj, Elm_Sel_Format format, const char *data,
2037 Elm_Xdnd_Action action,
2038 Elm_Drag_Icon_Create_Cb createicon, void *createdata,
2039 Elm_Drag_Pos dragpos, void *dragdata,
2040 Elm_Drag_Accept acceptcb, void *acceptdata,
2041 Elm_Drag_State dragdone, void *donecbdata)
2043 Ecore_X_Window xwin = _x11_elm_widget_xwin_get(obj);
2044 X11_Cnp_Selection *sel;
2045 Elm_Sel_Type xdnd = ELM_SEL_TYPE_XDND;
2047 int x, y, x2 = 0, y2 = 0, x3, y3;
2048 Evas_Object *icon = NULL;
2052 _x11_elm_cnp_init();
2054 cnp_debug("starting drag... %p\n", obj);
2058 cnp_debug("another obj is dragging...\n");
2062 ecore_x_dnd_type_set(xwin, "text/uri-list", EINA_TRUE);
2063 sel = _x11_selections + ELM_SEL_TYPE_XDND;
2064 sel->active = EINA_TRUE;
2066 sel->format = format;
2067 sel->selbuf = data ? strdup(data) : NULL;
2068 sel->action = action;
2070 dragaction = action;
2072 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
2073 _x11_drag_target_del, obj);
2074 /* TODO BUG: should NEVER have these as globals! They should be per context (window). */
2075 dragposcb = dragpos;
2076 dragposdata = dragdata;
2077 dragacceptcb = acceptcb;
2078 dragacceptdata = acceptdata;
2079 dragdonecb = dragdone;
2080 dragdonedata = donecbdata;
2081 /* TODO BUG: should increase dnd-awareness, in case it's drop target as well. See _x11_drag_mouse_up() */
2082 ecore_x_dnd_aware_set(xwin, EINA_TRUE);
2083 ecore_x_dnd_callback_pos_update_set(_x11_drag_move, NULL);
2084 ecore_x_dnd_self_begin(xwin, (unsigned char *)&xdnd, sizeof(Elm_Sel_Type));
2085 actx = _x11_dnd_action_rev_map(dragaction);
2086 ecore_x_dnd_source_action_set(actx);
2087 ecore_x_pointer_grab(xwin);
2088 handler_up = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
2090 (void *)(long)xwin);
2091 handler_status = ecore_event_handler_add(ECORE_X_EVENT_XDND_STATUS,
2092 _x11_dnd_status, NULL);
2093 dragwin = elm_win_add(NULL, "Elm-Drag", ELM_WIN_UTILITY);
2094 elm_win_alpha_set(dragwin, EINA_TRUE);
2095 elm_win_override_set(dragwin, EINA_TRUE);
2097 Evas_Object *win = elm_widget_top_get(obj);
2098 if (win && !strcmp(evas_object_type_get(win), "elm_win"))
2099 elm_win_rotation_set(dragwin, elm_win_rotation_get(win));
2103 Evas_Coord xoff = 0, yoff = 0;
2105 icon = createicon(createdata, dragwin, &xoff, &yoff);
2110 evas_object_geometry_get(icon, NULL, NULL, &w, &h);
2115 icon = elm_icon_add(dragwin);
2116 evas_object_size_hint_weight_set(icon, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
2117 evas_object_size_hint_align_set(icon, EVAS_HINT_FILL, EVAS_HINT_FILL);
2120 elm_win_resize_object_add(dragwin, icon);
2122 /* Position subwindow appropriately */
2123 ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
2124 ecore_evas_geometry_get(ee, &x, &y, NULL, NULL);
2127 dragwin_x_start = dragwin_x_end = x;
2128 dragwin_y_start = dragwin_y_end = y;
2129 evas_object_move(dragwin, x, y);
2130 evas_object_resize(dragwin, w, h);
2132 evas_object_show(icon);
2133 evas_object_show(dragwin);
2135 evas_pointer_canvas_xy_get(evas_object_evas_get(obj), &x3, &y3);
2143 _x11_elm_drag_action_set(Evas_Object *obj, Elm_Xdnd_Action action)
2147 _x11_elm_cnp_init();
2148 if (!dragwin) return EINA_FALSE;
2150 if (dragwidget != obj) return EINA_FALSE;
2151 if (dragaction == action) return EINA_TRUE;
2152 dragaction = action;
2153 actx = _x11_dnd_action_rev_map(dragaction);
2154 ecore_x_dnd_source_action_set(actx);
2159 _x11_elm_selection_selection_has_owner(Evas_Object *obj __UNUSED__)
2161 _x11_elm_cnp_init();
2162 return !!ecore_x_selection_owner_get(ECORE_X_ATOM_SELECTION_CLIPBOARD);
2167 #ifdef HAVE_ELEMENTARY_WAYLAND
2168 typedef struct _Wl_Cnp_Selection Wl_Cnp_Selection;
2170 struct _Wl_Cnp_Selection
2175 Evas_Object *widget;
2176 Evas_Object *requestwidget;
2179 static Eina_Bool _wl_elm_cnp_init(void);
2181 static Wl_Cnp_Selection wl_cnp_selection = {0, 0, NULL, NULL};
2182 static void _wl_sel_obj_del2(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__);
2183 static Eina_Bool _wl_elm_cnp_selection_set(Evas_Object *obj __UNUSED__, Elm_Sel_Type selection, Elm_Sel_Format format __UNUSED__, const void *selbuf, size_t buflen);
2184 static Eina_Bool _wl_elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format __UNUSED__, Elm_Drop_Cb datacb __UNUSED__, void *udata __UNUSED__);
2185 static Eina_Bool _wl_selection_send(void *udata, int type __UNUSED__, void *event);
2186 static Eina_Bool _wl_selection_receive(void *udata, int type __UNUSED__, void *event);
2189 _wl_sel_obj_del2(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
2191 Wl_Cnp_Selection *sel = data;
2192 if (sel->requestwidget == obj) sel->requestwidget = NULL;
2196 _wl_elm_cnp_selection_set(Evas_Object *obj __UNUSED__, Elm_Sel_Type selection, Elm_Sel_Format format __UNUSED__, const void *selbuf, size_t buflen)
2198 const char *types[10] = {0, };
2202 /* TODO: other EML_SEL_TYPE and ELM_SEL_FORMAT */
2203 if (ELM_SEL_TYPE_CLIPBOARD == selection)
2205 types[0] = "text/plain;charset=utf-8";
2206 ecore_wl_dnd_set_selection(ecore_wl_dnd_get(), types);
2208 if (wl_cnp_selection.selbuf) free(wl_cnp_selection.selbuf);
2209 wl_cnp_selection.selbuf = strdup((char*)selbuf);
2210 wl_cnp_selection.buflen = buflen;
2218 _wl_elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format __UNUSED__, Elm_Drop_Cb datacb __UNUSED__, void *udata __UNUSED__)
2222 /* For now, just avoid overlapped request */
2223 if (wl_cnp_selection.requestwidget) return EINA_FALSE;
2225 /* TODO: other EML_SEL_TYPE and ELM_SEL_FORMAT */
2226 if (ELM_SEL_TYPE_CLIPBOARD == selection)
2228 wl_cnp_selection.requestwidget = obj;
2229 evas_object_event_callback_add(wl_cnp_selection.requestwidget, EVAS_CALLBACK_DEL,
2230 _wl_sel_obj_del2, &wl_cnp_selection);
2231 ecore_wl_dnd_get_selection(ecore_wl_dnd_get(), "text/plain;charset=utf-8");
2237 _wl_selection_send(void *udata, int type __UNUSED__, void *event)
2240 int ret, len_remained;
2241 int len_written = 0;
2242 Wl_Cnp_Selection *sel = udata;
2243 Ecore_Wl_Event_Data_Source_Send *ev = event;
2247 len_remained = sel->buflen;
2250 while (len_written < sel->buflen)
2252 ret = write(ev->fd, buf, len_remained);
2253 if (ret == -1) break;
2256 len_remained -= ret;
2260 return ECORE_CALLBACK_PASS_ON;
2264 _wl_selection_receive(void *udata, int type __UNUSED__, void *event)
2266 Wl_Cnp_Selection *sel = udata;
2267 Ecore_Wl_Event_Selection_Data_Ready *ev = event;
2271 if (sel->requestwidget)
2275 /* TODO BUG: should never NEVER assume it's an elm_entry! */
2276 _elm_entry_entry_paste(sel->requestwidget, ev->data);
2280 evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL,
2281 _wl_sel_obj_del2, sel);
2282 sel->requestwidget = NULL;
2286 return ECORE_CALLBACK_PASS_ON;
2290 _wl_elm_cnp_init(void)
2292 static int _init_count = 0;
2294 if (_init_count > 0) return EINA_TRUE;
2297 ecore_event_handler_add(ECORE_WL_EVENT_DATA_SOURCE_SEND,
2298 _wl_selection_send, &wl_cnp_selection);
2299 ecore_event_handler_add(ECORE_WL_EVENT_SELECTION_DATA_READY,
2300 _wl_selection_receive, &wl_cnp_selection);
2311 ////////////////////////////////////////////////////////////////////////////
2312 // for local (Within 1 app/process) cnp (used by fb as fallback
2313 ////////////////////////////////////////////////////////////////////////////
2315 typedef struct _Local_Selinfo Local_Selinfo;
2317 struct _Local_Selinfo
2319 Elm_Sel_Format format;
2332 // for ELM_SEL_TYPE_PRIMARY, ELM_SEL_TYPE_SECONDARY, ELM_SEL_TYPE_XDND,
2333 // ELM_SEL_TYPE_CLIPBOARD
2334 static Local_Selinfo _local_selinfo[4];
2336 static void _local_get_job(void *data);
2338 static Eina_Bool _local_elm_cnp_init(void);
2339 static Eina_Bool _local_elm_cnp_selection_set(Evas_Object *obj __UNUSED__, Elm_Sel_Type selection, Elm_Sel_Format format, const void *selbuf, size_t buflen);
2340 static void _local_elm_cnp_selection_loss_callback_set(Evas_Object *obj __UNUSED__, Elm_Sel_Type selection __UNUSED__, Elm_Selection_Loss_Cb func __UNUSED__, const void *data __UNUSED__);
2341 static Eina_Bool _local_elm_object_cnp_selection_clear(Evas_Object *obj __UNUSED__, Elm_Sel_Type selection);
2342 static Eina_Bool _local_elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format __UNUSED__, Elm_Drop_Cb datacb, void *udata);
2343 static Eina_Bool _local_elm_drop_target_add(Evas_Object *obj __UNUSED__, Elm_Sel_Format format __UNUSED__,
2344 Elm_Drag_State entercb __UNUSED__, void *enterdata __UNUSED__,
2345 Elm_Drag_State leavecb __UNUSED__, void *leavedata __UNUSED__,
2346 Elm_Drag_Pos poscb __UNUSED__, void *posdata __UNUSED__,
2347 Elm_Drop_Cb dropcb __UNUSED__, void *cbdata __UNUSED__);
2348 static Eina_Bool _local_elm_drop_target_del(Evas_Object *obj __UNUSED__);
2349 static Eina_Bool _local_elm_drag_start(Evas_Object *obj __UNUSED__,
2350 Elm_Sel_Format format __UNUSED__,
2351 const char *data __UNUSED__,
2352 Elm_Xdnd_Action action __UNUSED__,
2353 Elm_Drag_Icon_Create_Cb createicon __UNUSED__,
2354 void *createdata __UNUSED__,
2355 Elm_Drag_Pos dragpos __UNUSED__,
2356 void *dragdata __UNUSED__,
2357 Elm_Drag_Accept acceptcb __UNUSED__,
2358 void *acceptdata __UNUSED__,
2359 Elm_Drag_State dragdone __UNUSED__,
2360 void *donecbdata __UNUSED__);
2361 static Eina_Bool _local_elm_selection_selection_has_owner(Evas_Object *obj __UNUSED__);
2364 _local_get_job(void *data)
2366 Local_Selinfo *info = data;
2367 Elm_Selection_Data ev;
2369 info->get.job = NULL;
2372 ev.format = info->format;
2373 ev.data = info->sel.buf;
2374 ev.len = info->sel.size;
2375 ev.action = ELM_XDND_ACTION_UNKNOWN;
2377 info->get.func(info->get.data, info->get.obj, &ev);
2381 _local_elm_cnp_init(void)
2383 static int _init_count = 0;
2385 if (_init_count > 0) return EINA_TRUE;
2387 memset(&(_local_selinfo), 0, sizeof(_local_selinfo));
2392 _local_elm_cnp_selection_set(Evas_Object *obj __UNUSED__,
2393 Elm_Sel_Type selection, Elm_Sel_Format format,
2394 const void *selbuf, size_t buflen)
2396 _local_elm_cnp_init();
2397 if (_local_selinfo[selection].sel.buf)
2398 free(_local_selinfo[selection].sel.buf);
2399 _local_selinfo[selection].format = format;
2400 _local_selinfo[selection].sel.buf = malloc(buflen);
2401 if (_local_selinfo[selection].sel.buf)
2403 memcpy(_local_selinfo[selection].sel.buf, selbuf, buflen);
2404 _local_selinfo[selection].sel.size = buflen;
2407 _local_selinfo[selection].sel.size = 0;
2412 _local_elm_cnp_selection_loss_callback_set(Evas_Object *obj __UNUSED__,
2413 Elm_Sel_Type selection __UNUSED__,
2414 Elm_Selection_Loss_Cb func __UNUSED__,
2415 const void *data __UNUSED__)
2417 _local_elm_cnp_init();
2418 // this doesnt need to do anything as we never lose selection to anyone
2423 _local_elm_object_cnp_selection_clear(Evas_Object *obj __UNUSED__,
2424 Elm_Sel_Type selection)
2426 _local_elm_cnp_init();
2427 if (_local_selinfo[selection].sel.buf)
2428 free(_local_selinfo[selection].sel.buf);
2429 _local_selinfo[selection].sel.buf = NULL;
2430 _local_selinfo[selection].sel.size = 0;
2435 _local_elm_cnp_selection_get(Evas_Object *obj,
2436 Elm_Sel_Type selection,
2437 Elm_Sel_Format format __UNUSED__,
2438 Elm_Drop_Cb datacb, void *udata)
2440 _local_elm_cnp_init();
2441 if (_local_selinfo[selection].get.job)
2442 ecore_job_del(_local_selinfo[selection].get.job);
2443 _local_selinfo[selection].get.obj = obj;
2444 _local_selinfo[selection].get.func = datacb;
2445 _local_selinfo[selection].get.data = udata;
2446 _local_selinfo[selection].get.job =
2447 ecore_job_add(_local_get_job, &(_local_selinfo[selection]));
2452 _local_elm_drop_target_add(Evas_Object *obj __UNUSED__,
2453 Elm_Sel_Format format __UNUSED__,
2454 Elm_Drag_State entercb __UNUSED__,
2455 void *enterdata __UNUSED__,
2456 Elm_Drag_State leavecb __UNUSED__,
2457 void *leavedata __UNUSED__,
2458 Elm_Drag_Pos poscb __UNUSED__,
2459 void *posdata __UNUSED__,
2460 Elm_Drop_Cb dropcb __UNUSED__,
2461 void *cbdata __UNUSED__)
2463 // XXX: implement me
2464 _local_elm_cnp_init();
2469 _local_elm_drop_target_del(Evas_Object *obj __UNUSED__)
2471 // XXX: implement me
2472 _local_elm_cnp_init();
2477 _local_elm_drag_start(Evas_Object *obj __UNUSED__,
2478 Elm_Sel_Format format __UNUSED__,
2479 const char *data __UNUSED__,
2480 Elm_Xdnd_Action action __UNUSED__,
2481 Elm_Drag_Icon_Create_Cb createicon __UNUSED__,
2482 void *createdata __UNUSED__,
2483 Elm_Drag_Pos dragpos __UNUSED__,
2484 void *dragdata __UNUSED__,
2485 Elm_Drag_Accept acceptcb __UNUSED__,
2486 void *acceptdata __UNUSED__,
2487 Elm_Drag_State dragdone __UNUSED__,
2488 void *donecbdata __UNUSED__)
2490 // XXX: implement me
2491 _local_elm_cnp_init();
2496 _local_elm_drag_action_set(Evas_Object *obj __UNUSED__,
2497 Elm_Xdnd_Action action __UNUSED__)
2499 // XXX: implement me
2500 _local_elm_cnp_init();
2505 _local_elm_selection_selection_has_owner(Evas_Object *obj __UNUSED__)
2507 _local_elm_cnp_init();
2508 if (_local_selinfo[ELM_SEL_TYPE_CLIPBOARD].sel.buf) return EINA_TRUE;
2518 // common internal funcs
2519 ////////////////////////////////////////////////////////////////////////////
2523 if (_elm_cnp_init_count > 0) return EINA_TRUE;
2524 _elm_cnp_init_count++;
2525 text_uri = eina_stringshare_add("text/uri-list");
2529 /* TODO: this should not be an actual tempfile, but rather encode the object
2530 * as http://dataurl.net/ if it's an image or similar. Evas should support
2531 * decoding it as memfile. */
2533 _tempfile_new(int size)
2537 const char *tmppath;
2541 info = calloc(1, sizeof(Tmp_Info));
2542 if (!info) return NULL;
2543 tmppath = getenv("TMP");
2544 if (!tmppath) tmppath = P_tmpdir;
2545 len = snprintf(NULL, 0, "%s/%sXXXXXX", tmppath, "elmcnpitem-");
2546 if (len < 0) goto on_error;
2548 info->filename = malloc(len);
2549 if (!info->filename) goto on_error;
2550 snprintf(info->filename,len,"%s/%sXXXXXX", tmppath, "elmcnpitem-");
2551 cur_umask = umask(S_IRWXO | S_IRWXG);
2552 info->fd = mkstemp(info->filename);
2554 if (info->fd < 0) goto on_error;
2558 /* And before someone says anything see POSIX 1003.1-2008 page 400 */
2561 pid = (long)getpid();
2562 /* Use pid instead of /proc/self: That way if can be passed around */
2563 len = snprintf(NULL,0,"/proc/%li/fd/%i", pid, info->fd);
2568 snprintf(tmp,len, "/proc/%li/fd/%i", pid, info->fd);
2569 unlink(info->filename);
2570 free(info->filename);
2571 info->filename = tmp;
2575 cnp_debug("filename is %s\n", info->filename);
2576 if (size < 1) goto on_error;
2578 if (ftruncate(info->fd, size))
2580 perror("ftruncate");
2583 eina_mmap_safety_enabled_set(EINA_TRUE);
2584 info->map = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, info->fd, 0);
2585 if (info->map == MAP_FAILED)
2593 if (info->fd > 0) close(info->fd);
2595 /* Set map to NULL and return */
2598 free(info->filename);
2608 _tmpinfo_free(Tmp_Info *info)
2610 if (!info) return 0;
2611 free(info->filename);
2617 _pasteimage_append(char *file, Evas_Object *entry)
2621 /* TODO BUG: shouldn't define absize=240x180. Prefer data:// instead of href:// -- may need support for evas. See http://dataurl.net/ */
2622 static const char *tagstring = "<item absize=240x180 href=file://%s></item>";
2624 if ((!file) || (!entry)) return EINA_FALSE;
2625 len = strlen(tagstring)+strlen(file);
2626 entrytag = alloca(len + 1);
2627 snprintf(entrytag, len + 1, tagstring, file);
2628 /* TODO BUG: should never NEVER assume it's an elm_entry! */
2629 _elm_entry_entry_paste(entry, entrytag);
2635 _entry_insert_filter(Evas_Object *entry, char *str)
2640 char *insertStr = str;
2642 if (elm_entry_single_line_get(entry))
2644 Eina_Strbuf *buf = eina_strbuf_new();
2647 eina_strbuf_append(buf, insertStr);
2648 eina_strbuf_replace_all(buf, "<br>", "");
2649 eina_strbuf_replace_all(buf, "<br/>", "");
2650 eina_strbuf_replace_all(buf, "<ps/>", "");
2651 insertStr = eina_strbuf_string_steal(buf);
2652 eina_strbuf_free(buf);
2655 cnp_debug("remove break tag: %s\n", insertStr);
2657 _elm_entry_entry_paste(entry, insertStr);
2659 if (insertStr != str)
2664 ////////////////////////////////////////////////////////////////////////////
2665 ////////////////////////////////////////////////////////////////////////////
2666 ////////////////////////////////////////////////////////////////////////////
2667 // common exposed funcs
2668 ////////////////////////////////////////////////////////////////////////////
2669 ////////////////////////////////////////////////////////////////////////////
2670 ////////////////////////////////////////////////////////////////////////////
2672 elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection,
2673 Elm_Sel_Format format, const void *selbuf, size_t buflen)
2675 if (selection > ELM_SEL_TYPE_CLIPBOARD) return EINA_FALSE;
2676 if (!_elm_cnp_init_count) _elm_cnp_init();
2677 #ifdef HAVE_ELEMENTARY_X
2678 if (_x11_elm_widget_xwin_get(obj))
2679 return _x11_elm_cnp_selection_set(obj, selection, format, selbuf, buflen);
2681 #ifdef HAVE_ELEMENTARY_WAYLAND
2682 if (elm_win_wl_window_get(obj))
2683 return _wl_elm_cnp_selection_set(obj, selection, format, selbuf, buflen);
2685 return _local_elm_cnp_selection_set(obj, selection, format, selbuf, buflen);
2689 elm_cnp_selection_loss_callback_set(Evas_Object *obj, Elm_Sel_Type selection,
2690 Elm_Selection_Loss_Cb func,
2693 if (selection > ELM_SEL_TYPE_CLIPBOARD) return;
2694 if (!_elm_cnp_init_count) _elm_cnp_init();
2695 #ifdef HAVE_ELEMENTARY_X
2696 if (_x11_elm_widget_xwin_get(obj))
2697 _x11_elm_cnp_selection_loss_callback_set(obj, selection, func, data);
2699 _local_elm_cnp_selection_loss_callback_set(obj, selection, func, data);
2703 elm_object_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type selection)
2705 if (selection > ELM_SEL_TYPE_CLIPBOARD) return EINA_FALSE;
2706 if (!_elm_cnp_init_count) _elm_cnp_init();
2707 #ifdef HAVE_ELEMENTARY_X
2708 if (_x11_elm_widget_xwin_get(obj))
2709 return _x11_elm_object_cnp_selection_clear(obj, selection);
2711 return _local_elm_object_cnp_selection_clear(obj, selection);
2715 elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection,
2716 Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata)
2718 if (selection > ELM_SEL_TYPE_CLIPBOARD) return EINA_FALSE;
2719 if (!_elm_cnp_init_count) _elm_cnp_init();
2720 #ifdef HAVE_ELEMENTARY_X
2721 if (_x11_elm_widget_xwin_get(obj))
2722 return _x11_elm_cnp_selection_get(obj, selection, format, datacb, udata);
2724 #ifdef HAVE_ELEMENTARY_WAYLAND
2725 if (elm_win_wl_window_get(obj))
2726 return _wl_elm_cnp_selection_get(obj, selection, format, datacb, udata);
2728 return _local_elm_cnp_selection_get(obj, selection, format, datacb, udata);
2731 ////////////////////////////////////////////////////////////////////////////
2734 * Add a widget as drop target.
2737 elm_drop_target_add(Evas_Object *obj, Elm_Sel_Format format,
2738 Elm_Drag_State entercb, void *enterdata,
2739 Elm_Drag_State leavecb, void *leavedata,
2740 Elm_Drag_Pos poscb, void *posdata,
2741 Elm_Drop_Cb dropcb, void *cbdata)
2743 if (!_elm_cnp_init_count) _elm_cnp_init();
2744 #ifdef HAVE_ELEMENTARY_X
2745 if (_x11_elm_widget_xwin_get(obj))
2746 return _x11_elm_drop_target_add(obj, format, entercb, enterdata,
2747 leavecb, leavedata, poscb, posdata,
2750 return _local_elm_drop_target_add(obj, format, entercb, enterdata,
2751 leavecb, leavedata, poscb, posdata,
2756 elm_drop_target_del(Evas_Object *obj)
2758 if (!_elm_cnp_init_count) _elm_cnp_init();
2759 #ifdef HAVE_ELEMENTARY_X
2760 if (_x11_elm_widget_xwin_get(obj))
2761 return _x11_elm_drop_target_del(obj);
2763 return _local_elm_drop_target_del(obj);
2767 elm_drag_start(Evas_Object *obj, Elm_Sel_Format format, const char *data,
2768 Elm_Xdnd_Action action,
2769 Elm_Drag_Icon_Create_Cb createicon, void *createdata,
2770 Elm_Drag_Pos dragpos, void *dragdata,
2771 Elm_Drag_Accept acceptcb, void *acceptdata,
2772 Elm_Drag_State dragdone, void *donecbdata)
2774 if (!_elm_cnp_init_count) _elm_cnp_init();
2775 #ifdef HAVE_ELEMENTARY_X
2776 if (_x11_elm_widget_xwin_get(obj))
2777 return _x11_elm_drag_start(obj, format, data, action,
2778 createicon, createdata,
2780 acceptcb, acceptdata,
2781 dragdone, donecbdata);
2783 return _local_elm_drag_start(obj, format, data, action,
2784 createicon, createdata,
2786 acceptcb, acceptdata,
2787 dragdone, donecbdata);
2791 elm_drag_action_set(Evas_Object *obj, Elm_Xdnd_Action action)
2793 if (!_elm_cnp_init_count) _elm_cnp_init();
2794 #ifdef HAVE_ELEMENTARY_X
2795 if (_x11_elm_widget_xwin_get(obj))
2796 return _x11_elm_drag_action_set(obj, action);
2798 return _local_elm_drag_action_set(obj, action);
2802 elm_selection_selection_has_owner(Evas_Object *obj)
2804 if (!_elm_cnp_init_count) _elm_cnp_init();
2805 #ifdef HAVE_ELEMENTARY_X
2806 if (_x11_elm_widget_xwin_get(obj))
2807 return _x11_elm_selection_selection_has_owner(obj);
2809 #ifdef HAVE_ELEMENTARY_WAYLAND
2810 if (elm_win_wl_window_get(obj))
2811 return ecore_wl_dnd_selection_has_owner(ecore_wl_dnd_get());
2813 return _local_elm_selection_selection_has_owner(obj);
2816 /* START - Support elm containers for Drag and Drop */
2817 /* START - Support elm containers for Drop */
2819 _drop_item_container_cmp(const void *d1,
2822 const Item_Container_Drop_Info *st = d1;
2823 return (((uintptr_t) (st->obj)) - ((uintptr_t) d2));
2827 _elm_item_container_pos_cb(void *data, Evas_Object *obj, Evas_Coord x, Evas_Coord y, Elm_Xdnd_Action action)
2828 { /* obj is the container pointer */
2829 Elm_Object_Item *it = NULL;
2832 Item_Container_Drop_Info *st =
2833 eina_list_search_unsorted(cont_drop_tg, _drop_item_container_cmp, obj);
2835 if (st && st->poscb)
2836 { /* Call container drop func with specific item pointer */
2839 evas_object_geometry_get(obj, &xo, &yo, NULL, NULL);
2841 it = st->itemgetcb(obj, x+xo, y+yo, &xposret, &yposret);
2843 st->poscb(data, obj, it, x, y, xposret, yposret, action);
2848 _elm_item_container_drop_cb(void *data, Evas_Object *obj , Elm_Selection_Data *ev)
2849 { /* obj is the container pointer */
2850 Elm_Object_Item *it = NULL;
2853 Item_Container_Drop_Info *st =
2854 eina_list_search_unsorted(cont_drop_tg, _drop_item_container_cmp, obj);
2856 if (st && st->dropcb)
2857 { /* Call container drop func with specific item pointer */
2860 evas_object_geometry_get(obj, &xo, &yo, NULL, NULL);
2862 it = st->itemgetcb(obj, ev->x+xo, ev->y+yo, &xposret, &yposret);
2864 return st->dropcb(data, obj, it, ev, xposret, yposret);
2871 elm_drop_item_container_del_internal(Evas_Object *obj, Eina_Bool full)
2873 Item_Container_Drop_Info *st =
2874 eina_list_search_unsorted(cont_drop_tg, _drop_item_container_cmp, obj);
2878 elm_drop_target_del(obj);
2879 st->itemgetcb= NULL;
2885 cont_drop_tg = eina_list_remove(cont_drop_tg, st);
2896 elm_drop_item_container_del(Evas_Object *obj)
2898 return elm_drop_item_container_del_internal(obj, EINA_TRUE);
2902 elm_drop_item_container_add(Evas_Object *obj,
2903 Elm_Sel_Format format,
2904 Elm_Xy_Item_Get_Cb itemgetcb,
2905 Elm_Drag_State entercb, void *enterdata,
2906 Elm_Drag_State leavecb, void *leavedata,
2907 Elm_Drag_Item_Container_Pos poscb, void *posdata,
2908 Elm_Drop_Item_Container_Cb dropcb, void *cbdata)
2910 Item_Container_Drop_Info *st;
2912 if (elm_drop_item_container_del_internal(obj, EINA_FALSE))
2913 { /* Updating info of existing obj */
2914 st = eina_list_search_unsorted(cont_drop_tg, _drop_item_container_cmp, obj);
2915 if (!st) return EINA_FALSE;
2919 st = calloc(1, sizeof(*st));
2920 if (!st) return EINA_FALSE;
2923 cont_drop_tg = eina_list_append(cont_drop_tg, st);
2926 st->itemgetcb = itemgetcb;
2928 st->dropcb = dropcb;
2929 elm_drop_target_add(obj, format,
2932 _elm_item_container_pos_cb, posdata,
2933 _elm_item_container_drop_cb, cbdata);
2937 /* END - Support elm containers for Drop */
2940 /* START - Support elm containers for Drag */
2942 _drag_item_container_cmp(const void *d1,
2945 const Item_Container_Drag_Info *st = d1;
2946 return (((uintptr_t) (st->obj)) - ((uintptr_t) d2));
2950 _cont_drag_done_cb(void *data, Evas_Object *obj __UNUSED__)
2952 Item_Container_Drag_Info *st = data;
2953 elm_widget_scroll_freeze_pop(st->obj);
2954 if (st->user_info.dragdone) st->user_info.dragdone(st->user_info.donecbdata, dragwidget, doaccept);
2958 _cont_obj_drag_start(void *data)
2959 { /* Start a drag-action when timer expires */
2960 cnp_debug("%s In\n", __FUNCTION__);
2961 Item_Container_Drag_Info *st = data;
2963 Elm_Drag_User_Info *info = &st->user_info;
2964 elm_widget_scroll_freeze_push(st->obj);
2965 evas_object_event_callback_del_full
2966 (st->obj, EVAS_CALLBACK_MOUSE_MOVE, _cont_obj_mouse_move, st);
2967 elm_drag_start( /* Commit the start only if data_get successful */
2968 st->obj, info->format,
2969 info->data, info->action,
2970 info->createicon, info->createdata,
2971 info->dragpos, info->dragdata,
2972 info->acceptcb, info->acceptdata,
2973 _cont_drag_done_cb, st);
2975 return ECORE_CALLBACK_CANCEL;
2979 _anim_st_free(Item_Container_Drag_Info *st)
2980 { /* Stops and free mem of ongoing animation */
2985 ecore_animator_del(st->ea);
2991 EINA_LIST_FREE(st->icons, sti)
2993 evas_object_del(sti->o);
3001 static inline Eina_List *
3002 _anim_icons_make(Eina_List *icons)
3003 { /* Make local copies of all icons, add them to list */
3004 Eina_List *list = NULL, *itr;
3007 EINA_LIST_FOREACH(icons, itr, o)
3008 { /* Now add icons to animation window */
3009 Anim_Icon *st = calloc(1, sizeof(*st));
3010 evas_object_geometry_get(o, &st->start_x, &st->start_y, &st->start_w, &st->start_h);
3011 evas_object_show(o);
3013 list = eina_list_append(list, st);
3020 _drag_anim_play(void *data, double pos)
3021 { /* Impl of the animation of icons, called on frame time */
3022 cnp_debug("%s In\n", __FUNCTION__);
3023 Item_Container_Drag_Info *st = data;
3031 st->ea = NULL; /* Avoid deleting on mouse up */
3032 EINA_LIST_FOREACH(st->icons, l, sti)
3033 evas_object_hide(sti->o);
3035 _cont_obj_drag_start(st); /* Start dragging */
3036 return ECORE_CALLBACK_CANCEL;
3040 evas_pointer_canvas_xy_get(st->e, &xm, &ym);
3041 EINA_LIST_FOREACH(st->icons, l, sti)
3044 w = sti->start_w + ((st->final_icon_w - sti->start_w) * pos);
3045 h = sti->start_h + ((st->final_icon_h - sti->start_h) * pos);
3046 x = sti->start_x - (pos * ((sti->start_x + (w/2) - xm)));
3047 y = sti->start_y - (pos * ((sti->start_y + (h/2) - ym)));
3048 evas_object_move(sti->o, x, y);
3049 evas_object_resize(sti->o, w, h);
3052 return ECORE_CALLBACK_RENEW;
3055 return ECORE_CALLBACK_CANCEL;
3058 static inline Eina_Bool
3059 _drag_anim_start(void *data)
3060 { /* Start default animation */
3061 cnp_debug("%s In\n", __FUNCTION__);
3062 Item_Container_Drag_Info *st = data;
3065 /* Now we need to build an (Anim_Icon *) list */
3066 st->icons = _anim_icons_make(st->user_info.icons);
3067 if (st->user_info.createicon)
3069 Evas_Object *temp_win = elm_win_add(NULL, "Temp", ELM_WIN_UTILITY);
3070 Evas_Object *final_icon = st->user_info.createicon(st->user_info.createdata, temp_win, NULL, NULL);
3071 evas_object_geometry_get(final_icon, NULL, NULL, &st->final_icon_w, &st->final_icon_h);
3072 evas_object_del(final_icon);
3073 evas_object_del(temp_win);
3075 st->ea = ecore_animator_timeline_add(st->anim_tm, _drag_anim_play, st);
3081 _cont_obj_anim_start(void *data)
3082 { /* Start a drag-action when timer expires */
3083 cnp_debug("%s In\n", __FUNCTION__);
3084 Item_Container_Drag_Info *st = data;
3085 int xposret, yposret; /* Unused */
3086 Elm_Object_Item *it = (st->itemgetcb) ?
3087 (st->itemgetcb(st->obj, st->x_down, st->y_down, &xposret, &yposret))
3091 st->user_info.format = ELM_SEL_FORMAT_TARGETS; /* Default */
3093 st->user_info.data = NULL;
3094 st->user_info.action = ELM_XDND_ACTION_COPY; /* Default */
3096 if (!it) /* Failed to get mouse-down item, abort drag */
3097 return ECORE_CALLBACK_CANCEL;
3100 { /* collect info then start animation or start dragging */
3101 if(st->data_get( /* Collect drag info */
3102 st->obj, /* The container object */
3103 it, /* Drag started on this item */
3106 if (st->user_info.icons)
3107 _drag_anim_start(st);
3112 // even if we don't manage the icons animation, we have
3113 // to wait until it is finished before beginning drag.
3114 st->tm = ecore_timer_add(st->anim_tm, _cont_obj_drag_start, st);
3117 _cont_obj_drag_start(st); /* Start dragging, no anim */
3122 return ECORE_CALLBACK_CANCEL;
3126 _cont_obj_mouse_down(
3129 Evas_Object *obj __UNUSED__,
3131 { /* Launch a timer to start dragging */
3132 Evas_Event_Mouse_Down *ev = event_info;
3133 cnp_debug("%s In - event %X\n", __FUNCTION__, ev->event_flags);
3134 if (ev->button != 1)
3135 return; /* We only process left-click at the moment */
3137 Item_Container_Drag_Info *st = data;
3138 evas_object_event_callback_add(st->obj, EVAS_CALLBACK_MOUSE_MOVE,
3139 _cont_obj_mouse_move, st);
3141 evas_object_event_callback_add(st->obj, EVAS_CALLBACK_MOUSE_UP,
3142 _cont_obj_mouse_up, st);
3145 ecore_timer_del(st->tm);
3148 st->x_down = ev->canvas.x;
3149 st->y_down = ev->canvas.y;
3150 st->tm = ecore_timer_add(st->tm_to_drag, _cont_obj_anim_start, st);
3153 static Eina_Bool elm_drag_item_container_del_internal(Evas_Object *obj, Eina_Bool full);
3156 _cont_obj_mouse_move(
3159 Evas_Object *obj __UNUSED__,
3161 { /* Cancel any drag waiting to start on timeout */
3163 cnp_debug("%s In\n", __FUNCTION__);
3164 if (((Evas_Event_Mouse_Move *)event_info)->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
3166 cnp_debug("%s event on hold - have to cancel DnD\n", __FUNCTION__);
3167 Item_Container_Drag_Info *st = data;
3168 evas_object_event_callback_del_full
3169 (st->obj, EVAS_CALLBACK_MOUSE_MOVE, _cont_obj_mouse_move, st);
3170 evas_object_event_callback_del_full
3171 (st->obj, EVAS_CALLBACK_MOUSE_UP, _cont_obj_mouse_up, st);
3172 elm_drag_item_container_del_internal(obj, EINA_FALSE);
3176 ecore_timer_del(st->tm);
3182 cnp_debug("%s Out\n", __FUNCTION__);
3189 Evas_Object *obj __UNUSED__,
3191 { /* Cancel any drag waiting to start on timeout */
3192 Item_Container_Drag_Info *st = data;
3194 cnp_debug("%s In\n", __FUNCTION__);
3195 if (((Evas_Event_Mouse_Up *)event_info)->button != 1)
3196 return; /* We only process left-click at the moment */
3198 evas_object_event_callback_del_full
3199 (st->obj, EVAS_CALLBACK_MOUSE_MOVE, _cont_obj_mouse_move, st);
3200 evas_object_event_callback_del_full
3201 (st->obj, EVAS_CALLBACK_MOUSE_UP, _cont_obj_mouse_up, st);
3205 ecore_timer_del(st->tm);
3213 elm_drag_item_container_del_internal(Evas_Object *obj, Eina_Bool full)
3215 Item_Container_Drag_Info *st =
3216 eina_list_search_unsorted(cont_drag_tg, _drag_item_container_cmp, obj);
3221 ecore_timer_del(st->tm); /* Cancel drag-start timer */
3223 if (st->ea) /* Cancel ongoing default animation */
3230 st->itemgetcb = NULL;;
3231 st->data_get = NULL;
3232 evas_object_event_callback_del_full
3233 (obj, EVAS_CALLBACK_MOUSE_DOWN, _cont_obj_mouse_down, st);
3234 cont_drag_tg = eina_list_remove(cont_drag_tg, st);
3245 elm_drag_item_container_del(Evas_Object *obj)
3247 return elm_drag_item_container_del_internal(obj, EINA_TRUE);
3251 elm_drag_item_container_add(
3255 Elm_Xy_Item_Get_Cb itemgetcb,
3256 Elm_Item_Container_Data_Get_Cb data_get)
3258 Item_Container_Drag_Info *st;
3260 if (elm_drag_item_container_del_internal(obj, EINA_FALSE))
3261 { /* Updating info of existing obj */
3262 st = eina_list_search_unsorted(cont_drag_tg, _drag_item_container_cmp, obj);
3263 if (!st) return EINA_FALSE;
3267 st = calloc(1, sizeof(*st));
3268 if (!st) return EINA_FALSE;
3271 cont_drag_tg = eina_list_append(cont_drag_tg, st);
3273 /* Register for mouse callback for container to start/abort drag */
3274 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
3275 _cont_obj_mouse_down, st);
3279 st->anim_tm = anim_tm;
3280 st->tm_to_drag = tm_to_drag;
3281 st->itemgetcb = itemgetcb;
3282 st->data_get = data_get;
3286 /* END - Support elm containers for Drag */
3287 /* END - Support elm containers for Drag and Drop */
3288 /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0 :*/