eolian: rename is_ref API to is_ptr to match syntax
[platform/upstream/efl.git] / src / lib / ecore_x / xcb / ecore_xcb_dnd.c
1 #include "ecore_xcb_private.h"
2
3 /* local structures */
4 typedef struct _Version_Cache_Item
5 {
6    Ecore_X_Window win;
7    int            ver;
8 } Version_Cache_Item;
9
10 /* local function prototypes */
11 static Eina_Bool _ecore_xcb_dnd_converter_copy(char         *target EINA_UNUSED,
12                                                void         *data,
13                                                int           size,
14                                                void        **data_ret,
15                                                int          *size_ret,
16                                                Ecore_X_Atom *tprop EINA_UNUSED,
17                                                int          *count EINA_UNUSED);
18
19 /* local variables */
20 static int _ecore_xcb_dnd_init_count = 0;
21 static Ecore_X_DND_Source *_source = NULL;
22 static Ecore_X_DND_Target *_target = NULL;
23 static Version_Cache_Item *_version_cache = NULL;
24 static int _version_cache_num = 0, _version_cache_alloc = 0;
25 static void (*_posupdatecb)(void *,
26                             Ecore_X_Xdnd_Position *);
27 static void *_posupdatedata;
28
29 /* external variables */
30 EAPI int ECORE_X_EVENT_XDND_ENTER = 0;
31 EAPI int ECORE_X_EVENT_XDND_POSITION = 0;
32 EAPI int ECORE_X_EVENT_XDND_STATUS = 0;
33 EAPI int ECORE_X_EVENT_XDND_LEAVE = 0;
34 EAPI int ECORE_X_EVENT_XDND_DROP = 0;
35 EAPI int ECORE_X_EVENT_XDND_FINISHED = 0;
36
37 void
38 _ecore_xcb_dnd_init(void)
39 {
40    LOGFN(__FILE__, __LINE__, __FUNCTION__);
41
42    if (!_ecore_xcb_dnd_init_count)
43      {
44         _source = calloc(1, sizeof(Ecore_X_DND_Source));
45         if (!_source) return;
46         _source->version = ECORE_X_DND_VERSION;
47         _source->win = XCB_NONE;
48         _source->dest = XCB_NONE;
49         _source->state = ECORE_X_DND_SOURCE_IDLE;
50         _source->prev.window = 0;
51
52         _target = calloc(1, sizeof(Ecore_X_DND_Target));
53         if (!_target)
54           {
55              free(_source);
56              _source = NULL;
57              return;
58           }
59         _target->win = XCB_NONE;
60         _target->source = XCB_NONE;
61         _target->state = ECORE_X_DND_TARGET_IDLE;
62
63         ECORE_X_EVENT_XDND_ENTER = ecore_event_type_new();
64         ECORE_X_EVENT_XDND_POSITION = ecore_event_type_new();
65         ECORE_X_EVENT_XDND_STATUS = ecore_event_type_new();
66         ECORE_X_EVENT_XDND_LEAVE = ecore_event_type_new();
67         ECORE_X_EVENT_XDND_DROP = ecore_event_type_new();
68         ECORE_X_EVENT_XDND_FINISHED = ecore_event_type_new();
69      }
70    _ecore_xcb_dnd_init_count++;
71 }
72
73 void
74 _ecore_xcb_dnd_shutdown(void)
75 {
76    LOGFN(__FILE__, __LINE__, __FUNCTION__);
77
78    _ecore_xcb_dnd_init_count--;
79    if (_ecore_xcb_dnd_init_count > 0) return;
80    if (_source) free(_source);
81    _source = NULL;
82    if (_target) free(_target);
83    _target = NULL;
84    _ecore_xcb_dnd_init_count = 0;
85 }
86
87 EAPI void
88 ecore_x_dnd_send_status(Eina_Bool         will_accept,
89                         Eina_Bool         suppress,
90                         Ecore_X_Rectangle rect,
91                         Ecore_X_Atom      action)
92 {
93    xcb_client_message_event_t ev;
94
95    LOGFN(__FILE__, __LINE__, __FUNCTION__);
96    CHECK_XCB_CONN;
97
98    if (_target->state == ECORE_X_DND_TARGET_IDLE) return;
99
100    memset(&ev, 0, sizeof(xcb_client_message_event_t));
101
102    _target->will_accept = will_accept;
103
104    ev.response_type = XCB_CLIENT_MESSAGE;
105    ev.type = ECORE_X_ATOM_XDND_STATUS;
106    ev.format = 32;
107    ev.window = _target->source;
108    ev.data.data32[0] = _target->win;
109    ev.data.data32[1] = 0;
110    if (will_accept) ev.data.data32[1] |= 0x1UL;
111    if (!suppress) ev.data.data32[1] |= 0x2UL;
112
113    ev.data.data32[2] = rect.x;
114    ev.data.data32[2] <<= 16;
115    ev.data.data32[2] |= rect.y;
116    ev.data.data32[3] = rect.width;
117    ev.data.data32[3] <<= 16;
118    ev.data.data32[3] |= rect.height;
119
120    if (will_accept)
121      ev.data.data32[4] = action;
122    else
123      ev.data.data32[4] = XCB_NONE;
124    _target->accepted_action = action;
125
126    xcb_send_event(_ecore_xcb_conn, 0, _target->source,
127                   XCB_EVENT_MASK_NO_EVENT, (const char *)&ev);
128 //   ecore_x_flush();
129 }
130
131 EAPI void
132 ecore_x_dnd_aware_set(Ecore_X_Window win,
133                       Eina_Bool      on)
134 {
135    Ecore_X_Atom prop_data = ECORE_X_DND_VERSION;
136
137    LOGFN(__FILE__, __LINE__, __FUNCTION__);
138
139    if (on)
140      ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_AWARE,
141                                       ECORE_X_ATOM_ATOM, 32, &prop_data, 1);
142    else
143      ecore_x_window_prop_property_del(win, ECORE_X_ATOM_XDND_AWARE);
144 }
145
146 EAPI int
147 ecore_x_dnd_version_get(Ecore_X_Window win)
148 {
149    unsigned char *data;
150    int num = 0;
151    Version_Cache_Item *t;
152
153    LOGFN(__FILE__, __LINE__, __FUNCTION__);
154
155    if (_source->state == ECORE_X_DND_SOURCE_DRAGGING)
156      {
157         if (_version_cache)
158           {
159              int i = 0;
160
161              for (i = 0; i < _version_cache_num; i++)
162                {
163                   if (_version_cache[i].win == win)
164                     return _version_cache[i].ver;
165                }
166           }
167      }
168
169    if (ecore_x_window_prop_property_get(win, ECORE_X_ATOM_XDND_AWARE,
170                                         ECORE_X_ATOM_ATOM, 32, &data, &num))
171      {
172         int version = 0;
173
174         version = (int)*data;
175         free(data);
176         if (_source->state == ECORE_X_DND_SOURCE_DRAGGING)
177           {
178              _version_cache_num++;
179              if (_version_cache_num > _version_cache_alloc)
180                _version_cache_alloc += 16;
181              t = realloc(_version_cache,
182                          _version_cache_alloc * sizeof(Version_Cache_Item));
183              if (!t) return 0;
184              _version_cache = t;
185              _version_cache[_version_cache_num - 1].win = win;
186              _version_cache[_version_cache_num - 1].ver = version;
187           }
188         return version;
189      }
190
191    if (_source->state == ECORE_X_DND_SOURCE_DRAGGING)
192      {
193         _version_cache_num++;
194         if (_version_cache_num > _version_cache_alloc)
195           _version_cache_alloc += 16;
196         t = realloc(_version_cache,
197                     _version_cache_alloc * sizeof(Version_Cache_Item));
198         if (!t) return 0;
199         _version_cache = t;
200         _version_cache[_version_cache_num - 1].win = win;
201         _version_cache[_version_cache_num - 1].ver = 0;
202      }
203
204    return 0;
205 }
206
207 EAPI Eina_Bool
208 ecore_x_dnd_type_isset(Ecore_X_Window win,
209                        const char    *type)
210 {
211    int num = 0, i = 0;
212    Eina_Bool ret = EINA_FALSE;
213    unsigned char *data;
214    Ecore_X_Atom *atoms, atom;
215
216    LOGFN(__FILE__, __LINE__, __FUNCTION__);
217    CHECK_XCB_CONN;
218
219    if (!ecore_x_window_prop_property_get(win, ECORE_X_ATOM_XDND_TYPE_LIST,
220                                          ECORE_X_ATOM_ATOM, 32, &data, &num))
221      return ret;
222
223    atom = ecore_x_atom_get(type);
224    atoms = (Ecore_X_Atom *)data;
225    for (i = 0; i < num; ++i)
226      {
227         if (atom == atoms[i])
228           {
229              ret = EINA_TRUE;
230              break;
231           }
232      }
233
234    free(data);
235    return ret;
236 }
237
238 EAPI void
239 ecore_x_dnd_type_set(Ecore_X_Window win,
240                      const char    *type,
241                      Eina_Bool      on)
242 {
243    Ecore_X_Atom atom, *oldset = NULL, *newset = NULL;
244    int i = 0, j = 0, num = 0;
245    unsigned char *data = NULL, *old_data = NULL;
246
247    LOGFN(__FILE__, __LINE__, __FUNCTION__);
248    CHECK_XCB_CONN;
249
250    atom = ecore_x_atom_get(type);
251    ecore_x_window_prop_property_get(win, ECORE_X_ATOM_XDND_TYPE_LIST,
252                                     ECORE_X_ATOM_ATOM, 32, &old_data, &num);
253    oldset = (Ecore_X_Atom *)old_data;
254    if (on)
255      {
256         if (ecore_x_dnd_type_isset(win, type))
257           {
258              free(old_data);
259              return;
260           }
261         newset = calloc(num + 1, sizeof(Ecore_X_Atom));
262         if (!newset) return;
263         data = (unsigned char *)newset;
264         for (i = 0; i < num; i++)
265           newset[i + 1] = oldset[i];
266         newset[0] = atom;
267         ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_TYPE_LIST,
268                                          ECORE_X_ATOM_ATOM, 32, data, num + 1);
269      }
270    else
271      {
272         if (!ecore_x_dnd_type_isset(win, type))
273           {
274              free(old_data);
275              return;
276           }
277         newset = calloc(num - 1, sizeof(Ecore_X_Atom));
278         if (!newset)
279           {
280              free(old_data);
281              return;
282           }
283         data = (unsigned char *)newset;
284         for (i = 0; i < num; i++)
285           if (oldset[i] != atom)
286             newset[j++] = oldset[i];
287         ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_TYPE_LIST,
288                                          ECORE_X_ATOM_ATOM, 32, data, num - 1);
289      }
290    free(oldset);
291    free(newset);
292 }
293
294 EAPI void
295 ecore_x_dnd_types_set(Ecore_X_Window win,
296                       const char   **types,
297                       unsigned int   num_types)
298 {
299    Ecore_X_Atom *newset = NULL;
300    unsigned int i;
301    unsigned char *data = NULL;
302
303    LOGFN(__FILE__, __LINE__, __FUNCTION__);
304    CHECK_XCB_CONN;
305
306    if (!num_types)
307      ecore_x_window_prop_property_del(win, ECORE_X_ATOM_XDND_TYPE_LIST);
308    else
309      {
310         newset = calloc(num_types, sizeof(Ecore_X_Atom));
311         if (!newset) return;
312
313         data = (unsigned char *)newset;
314         for (i = 0; i < num_types; i++)
315           {
316              newset[i] = ecore_x_atom_get(types[i]);
317              ecore_x_selection_converter_atom_add(newset[i],
318                                                   _ecore_xcb_dnd_converter_copy);
319           }
320         ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_TYPE_LIST,
321                                          ECORE_X_ATOM_ATOM, 32, data,
322                                          num_types);
323         free(newset);
324      }
325 }
326
327 EAPI void
328 ecore_x_dnd_actions_set(Ecore_X_Window win,
329                         Ecore_X_Atom  *actions,
330                         unsigned int   num_actions)
331 {
332    unsigned int i;
333    unsigned char *data = NULL;
334
335    LOGFN(__FILE__, __LINE__, __FUNCTION__);
336    CHECK_XCB_CONN;
337
338    if (!num_actions)
339      ecore_x_window_prop_property_del(win, ECORE_X_ATOM_XDND_ACTION_LIST);
340    else
341      {
342         data = (unsigned char *)actions;
343         for (i = 0; i < num_actions; i++)
344           ecore_x_selection_converter_atom_add(actions[i],
345                                                _ecore_xcb_dnd_converter_copy);
346         ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_ACTION_LIST,
347                                          ECORE_X_ATOM_ATOM, 32, data,
348                                          num_actions);
349      }
350 }
351
352 /**
353  * The DND position update cb is called Ecore_X sends a DND position to a
354  * client.
355  *
356  * It essentially mirrors some of the data sent in the position message.
357  * Generally this cb should be set just before position update is called.
358  * Please note well you need to look after your own data pointer if someone
359  * trashes you position update cb set.
360  *
361  * It is considered good form to clear this when the dnd event finishes.
362  *
363  * @param cb Callback to updated each time ecore_x sends a position update.
364  * @param data User data.
365  */
366 EAPI void
367 ecore_x_dnd_callback_pos_update_set(void (*cb)(void *, Ecore_X_Xdnd_Position *data),
368                                     const void *data)
369 {
370    _posupdatecb = cb;
371    _posupdatedata = (void *)data;
372 }
373
374 static Eina_Bool
375 _ecore_x_dnd_begin(Ecore_X_Window source, Eina_Bool self, unsigned char *data, int size)
376 {
377    LOGFN(__FILE__, __LINE__, __FUNCTION__);
378
379    if (!ecore_x_dnd_version_get(source)) return EINA_FALSE;
380
381    /* Take ownership of XdndSelection */
382    if (!ecore_x_selection_xdnd_set(source, data, size)) return EINA_FALSE;
383
384    if (_version_cache)
385      {
386         free(_version_cache);
387         _version_cache = NULL;
388         _version_cache_num = 0;
389         _version_cache_alloc = 0;
390      }
391
392    ecore_x_window_shadow_tree_flush();
393
394    _source->win = source;
395    if (!self) ecore_x_window_ignore_set(_source->win, 1);
396    _source->state = ECORE_X_DND_SOURCE_DRAGGING;
397    _source->time = _ecore_xcb_events_last_time_get();
398    _source->prev.window = 0;
399
400    /* Default Accepted Action: move */
401    _source->action = ECORE_X_ATOM_XDND_ACTION_MOVE;
402    _source->accepted_action = XCB_NONE;
403    _source->dest = XCB_NONE;
404
405    return EINA_TRUE;
406 }
407
408 static Eina_Bool
409 _ecore_x_dnd_drop(Eina_Bool self)
410 {
411    xcb_client_message_event_t ev;
412    Eina_Bool status = EINA_FALSE;
413
414    LOGFN(__FILE__, __LINE__, __FUNCTION__);
415    CHECK_XCB_CONN;
416
417    memset(&ev, 0, sizeof(xcb_client_message_event_t));
418
419    if (_source->dest)
420      {
421         ev.response_type = XCB_CLIENT_MESSAGE;
422         ev.format = 32;
423         ev.window = _source->dest;
424
425         if (_source->will_accept)
426           {
427              ev.type = ECORE_X_ATOM_XDND_DROP;
428              ev.data.data32[0] = _source->win;
429              ev.data.data32[1] = 0;
430              ev.data.data32[2] = _source->time;
431
432              xcb_send_event(_ecore_xcb_conn, 0, _source->dest,
433                             XCB_EVENT_MASK_NO_EVENT, (const char *)&ev);
434 //             ecore_x_flush();
435              _source->state = ECORE_X_DND_SOURCE_DROPPED;
436              status = EINA_TRUE;
437           }
438         else
439           {
440              ev.type = ECORE_X_ATOM_XDND_LEAVE;
441              ev.data.data32[0] = _source->win;
442              ev.data.data32[1] = 0;
443
444              xcb_send_event(_ecore_xcb_conn, 0, _source->dest,
445                             XCB_EVENT_MASK_NO_EVENT, (const char *)&ev);
446 //             ecore_x_flush();
447              _source->state = ECORE_X_DND_SOURCE_IDLE;
448           }
449      }
450    else
451      {
452         ecore_x_selection_xdnd_clear();
453         _source->state = ECORE_X_DND_SOURCE_IDLE;
454      }
455
456    if (!self) ecore_x_window_ignore_set(_source->win, 0);
457    _source->prev.window = 0;
458
459    return status;
460 }
461
462 EAPI Eina_Bool
463 ecore_x_dnd_begin(Ecore_X_Window source,
464                   unsigned char *data,
465                   int            size)
466 {
467    return _ecore_x_dnd_begin(source, EINA_FALSE, data, size);
468 }
469
470 EAPI Eina_Bool
471 ecore_x_dnd_drop(void)
472 {
473    return _ecore_x_dnd_drop(EINA_FALSE);
474 }
475
476 EAPI Eina_Bool
477 ecore_x_dnd_self_begin(Ecore_X_Window source,
478                        unsigned char *data,
479                        int            size)
480 {
481    return _ecore_x_dnd_begin(source, EINA_TRUE, data, size);
482 }
483
484 EAPI Eina_Bool
485 ecore_x_dnd_self_drop(void)
486 {
487    return _ecore_x_dnd_drop(EINA_TRUE);
488 }
489
490 EAPI void
491 ecore_x_dnd_send_finished(void)
492 {
493    xcb_client_message_event_t ev;
494
495    LOGFN(__FILE__, __LINE__, __FUNCTION__);
496    CHECK_XCB_CONN;
497
498    if (_target->state == ECORE_X_DND_TARGET_IDLE) return;
499
500    memset(&ev, 0, sizeof(xcb_client_message_event_t));
501
502    ev.response_type = XCB_CLIENT_MESSAGE;
503    ev.format = 32;
504    ev.type = ECORE_X_ATOM_XDND_FINISHED;
505    ev.window = _target->source;
506    ev.data.data32[0] = _target->win;
507    ev.data.data32[1] = 0;
508    ev.data.data32[2] = 0;
509    if (_target->will_accept)
510      {
511         ev.data.data32[1] |= 0x1UL;
512         ev.data.data32[2] = _target->accepted_action;
513      }
514
515    xcb_send_event(_ecore_xcb_conn, 0, _target->source,
516                   XCB_EVENT_MASK_NO_EVENT, (const char *)&ev);
517 //   ecore_x_flush();
518    _target->state = ECORE_X_DND_TARGET_IDLE;
519 }
520
521 EAPI void
522 ecore_x_dnd_source_action_set(Ecore_X_Atom action)
523 {
524    LOGFN(__FILE__, __LINE__, __FUNCTION__);
525
526    _source->action = action;
527    if (_source->prev.window)
528      _ecore_xcb_dnd_drag(_source->prev.window,
529                          _source->prev.x, _source->prev.y);
530 }
531
532 Ecore_X_DND_Source *
533 _ecore_xcb_dnd_source_get(void)
534 {
535    return _source;
536 }
537
538 Ecore_X_DND_Target *
539 _ecore_xcb_dnd_target_get(void)
540 {
541    return _target;
542 }
543
544 void
545 _ecore_xcb_dnd_drag(Ecore_X_Window root,
546                     int            x,
547                     int            y)
548 {
549    xcb_client_message_event_t ev;
550    Ecore_X_Window win, *skip;
551    Ecore_X_Xdnd_Position pos;
552    int num = 0;
553
554    LOGFN(__FILE__, __LINE__, __FUNCTION__);
555    CHECK_XCB_CONN;
556
557    if (_source->state != ECORE_X_DND_SOURCE_DRAGGING) return;
558
559    memset(&ev, 0, sizeof(xcb_client_message_event_t));
560
561    ev.response_type = XCB_CLIENT_MESSAGE;
562    ev.format = 32;
563
564    skip = ecore_x_window_ignore_list(&num);
565    win = ecore_x_window_shadow_tree_at_xy_with_skip_get(root, x, y, skip, num);
566    while ((win) && !(ecore_x_dnd_version_get(win)))
567      win = ecore_x_window_shadow_parent_get(root, win);
568
569    if ((_source->dest) && (win != _source->dest))
570      {
571         ev.window = _source->dest;
572         ev.type = ECORE_X_ATOM_XDND_LEAVE;
573         ev.data.data32[0] = _source->win;
574         ev.data.data32[1] = 0;
575
576         xcb_send_event(_ecore_xcb_conn, 0, _source->dest,
577                        XCB_EVENT_MASK_NO_EVENT, (const char *)&ev);
578 //        ecore_x_flush();
579         _source->suppress = 0;
580      }
581
582    if (win)
583      {
584         int x1, x2, y1, y2;
585
586         _source->version = MIN(ECORE_X_DND_VERSION,
587                                ecore_x_dnd_version_get(win));
588         if (win != _source->dest)
589           {
590              int i = 0;
591              unsigned char *data;
592              Ecore_X_Atom *types;
593
594              ecore_x_window_prop_property_get(_source->win,
595                                               ECORE_X_ATOM_XDND_TYPE_LIST,
596                                               ECORE_X_ATOM_ATOM, 32,
597                                               &data, &num);
598              types = (Ecore_X_Atom *)data;
599              ev.window = win;
600              ev.type = ECORE_X_ATOM_XDND_ENTER;
601              ev.data.data32[0] = _source->win;
602              ev.data.data32[1] = 0;
603              if (num > 3)
604                ev.data.data32[1] |= 0x1UL;
605              else
606                ev.data.data32[1] &= 0xfffffffeUL;
607              ev.data.data32[1] |= ((unsigned long)_source->version) << 24;
608
609              for (i = 2; i < 5; i++)
610                ev.data.data32[i] = 0;
611              for (i = 0; i < MIN(num, 3); ++i)
612                ev.data.data32[i + 2] = types[i];
613              free(data);
614
615              xcb_send_event(_ecore_xcb_conn, 0, win,
616                             XCB_EVENT_MASK_NO_EVENT, (const char *)&ev);
617 //             ecore_x_flush();
618              _source->await_status = 0;
619              _source->will_accept = 0;
620           }
621
622         x1 = _source->rectangle.x;
623         x2 = _source->rectangle.x + _source->rectangle.width;
624         y1 = _source->rectangle.y;
625         y2 = _source->rectangle.y + _source->rectangle.height;
626
627         if ((!_source->await_status) || (!_source->suppress) ||
628             ((x < x1) || (x > x2) || (y < y1) || (y > y2)))
629           {
630              ev.window = win;
631              ev.type = ECORE_X_ATOM_XDND_POSITION;
632              ev.data.data32[0] = _source->win;
633              ev.data.data32[1] = 0;
634              ev.data.data32[2] = ((x << 16) & 0xffff0000) | (y & 0xffff);
635              ev.data.data32[3] = _source->time;
636              ev.data.data32[4] = _source->action;
637
638              xcb_send_event(_ecore_xcb_conn, 0, win,
639                             XCB_EVENT_MASK_NO_EVENT, (const char *)&ev);
640 //             ecore_x_flush();
641              _source->await_status = 1;
642           }
643      }
644
645    if (_posupdatecb)
646      {
647         pos.position.x = x;
648         pos.position.y = y;
649         pos.win = win;
650         pos.prev = _source->dest;
651         _posupdatecb(_posupdatedata, &pos);
652      }
653
654    _source->prev.x = x;
655    _source->prev.y = y;
656    _source->prev.window = root;
657    _source->dest = win;
658 }
659
660 EAPI Ecore_X_Atom
661 ecore_x_dnd_source_action_get(void)
662 {
663    return _source->action;
664 }
665
666 /* local functions */
667 static Eina_Bool
668 _ecore_xcb_dnd_converter_copy(char         *target EINA_UNUSED,
669                               void         *data,
670                               int           size,
671                               void        **data_ret,
672                               int          *size_ret,
673                               Ecore_X_Atom *tprop EINA_UNUSED,
674                               int          *count EINA_UNUSED)
675 {
676    Ecore_Xcb_Textproperty text_prop;
677    Ecore_Xcb_Encoding_Style style = XcbTextStyle;
678    char *mystr;
679
680    LOGFN(__FILE__, __LINE__, __FUNCTION__);
681
682    if ((!data) || (!size)) return EINA_FALSE;
683
684    mystr = calloc(1, size + 1);
685    if (!mystr) return EINA_FALSE;
686
687    memcpy(mystr, data, size);
688    if (_ecore_xcb_mb_textlist_to_textproperty(&mystr, 1, style, &text_prop))
689      {
690         int len;
691
692         len = strlen((char *)text_prop.value) + 1;
693         if (!(*data_ret = malloc(len)))
694           {
695              free(mystr);
696              return EINA_FALSE;
697           }
698         memcpy(*data_ret, text_prop.value, len);
699         *size_ret = len;
700         free(text_prop.value);
701         free(mystr);
702         return EINA_TRUE;
703      }
704    else
705      {
706         free(mystr);
707         return EINA_FALSE;
708      }
709 }
710
711 EAPI Eina_Bool
712 ecore_x_dnd_abort(Ecore_X_Window xwin_source)
713 {
714    if (xwin_source == _source->win)
715      {
716         _source->will_accept = 0;
717         return ecore_x_dnd_self_drop();
718      }
719    else return EINA_FALSE;
720 }