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