summaryrefslogtreecommitdiff
path: root/src/lib/efl_wl/x11.x
diff options
context:
space:
mode:
authorMike Blumenkrantz <zmike@osg.samsung.com>2017-06-30 14:59:21 -0400
committerMike Blumenkrantz <zmike@osg.samsung.com>2017-06-30 14:59:55 -0400
commitc2fde93c9ef1108c0809a538cf2ec482ed8369a9 (patch)
treed9879e4ebea4d25cda1a6cc1268461ad0d669c3b /src/lib/efl_wl/x11.x
parent3775a9645da7e92599babccfe8454304cec367b7 (diff)
efl_wl: a multiseat wayland compositor in an evas smart object
build when wayland support is enabled and provide two test/demo cases beta api @feature Reviewed-By: Cedric BAIL <cedric@osg.samsung.com>
Diffstat (limited to '')
-rw-r--r--src/lib/efl_wl/x11.x563
1 files changed, 563 insertions, 0 deletions
diff --git a/src/lib/efl_wl/x11.x b/src/lib/efl_wl/x11.x
new file mode 100644
index 0000000000..f554b8eaaf
--- /dev/null
+++ b/src/lib/efl_wl/x11.x
@@ -0,0 +1,563 @@
1#define WL_TEXT_STR "text/plain;charset=utf-8"
2#define INCR_CHUNK_SIZE 1 << 17
3
4static void (*xconvertselection)(Ecore_X_Display *, Ecore_X_Atom, Ecore_X_Atom, Ecore_X_Atom, Ecore_X_Window, Ecore_X_Time);
5static Ecore_X_Atom string_atom;
6static Ecore_X_Atom comp_dnd_atom;
7static Ecore_X_Atom timestamp_atom;
8static Ecore_X_Atom incr_atom;
9static Ecore_X_Atom int_atom;
10
11static Eina_Hash *pipes;
12
13typedef struct
14{
15 Ecore_Fd_Handler *fdh;
16 Comp_Data_Device_Source *source;
17 Ecore_X_Window win;
18 Ecore_X_Atom atom;
19 Ecore_X_Atom selection;
20 Ecore_X_Atom property;
21 Eina_Binbuf *buf;
22 Eina_Bool incr : 1;
23} Pipe;
24
25static void
26_pipe_free(Pipe *p)
27{
28 close(ecore_main_fd_handler_fd_get(p->fdh));
29 ecore_main_fd_handler_del(p->fdh);
30 eina_binbuf_free(p->buf);
31 free(p);
32}
33
34static void
35_incr_update(Pipe *p, Eina_Bool success)
36{
37 ecore_x_selection_notify_send(p->win, p->selection, p->atom, (!!success) * p->property, 0);
38}
39
40static void
41_incr_upload(Pipe *p)
42{
43 size_t size;
44
45 size = eina_binbuf_length_get(p->buf);
46 size = MIN(size, INCR_CHUNK_SIZE);
47 ecore_x_window_prop_property_set(p->win, p->property, p->atom, 8, (void*)eina_binbuf_string_get(p->buf), size);
48 eina_binbuf_free(p->buf);
49 p->buf = NULL;
50}
51
52static Eina_Bool
53x11_offer_write(void *data, Ecore_Fd_Handler *fdh)
54{
55 Comp_Data_Device_Transfer *dt = data;
56 int len = -1;
57
58 if (ecore_main_fd_handler_active_get(fdh, ECORE_FD_WRITE))
59 {
60 len = write(ecore_main_fd_handler_fd_get(fdh),
61 eina_binbuf_string_get(dt->source->reader_data) + dt->offset,
62 eina_binbuf_length_get(dt->source->reader_data) - dt->offset);
63 if (len > 0) dt->offset += len;
64 }
65
66 if ((len <= 0) || (dt->offset == eina_binbuf_length_get(dt->source->reader_data)))
67 {
68 fdh_del(fdh);
69 eina_stringshare_del(dt->mime_type);
70 dt->source->transfers = eina_inlist_remove(dt->source->transfers, EINA_INLIST_GET(dt));
71
72 if (dt->source->x11_owner)
73 {
74 Ecore_Window win = ecore_evas_window_get(ecore_evas_ecore_evas_get(dt->source->seat->c->evas));
75 if (dt->type == COMP_DATA_DEVICE_OFFER_TYPE_DND)
76 ecore_x_client_message32_send(dt->source->x11_owner,
77 ECORE_X_ATOM_XDND_FINISHED, ECORE_X_EVENT_MASK_NONE,
78 win, (len >= 0), action_convert(dt->source->current_dnd_action), 0, 0);
79 ecore_x_window_prop_property_del(win, ECORE_X_ATOM_XDND_TYPE_LIST);
80 if (dt->source == dt->source->seat->drag.source)
81 dt->source->seat->drag.source = NULL;
82 }
83
84 if ((!dt->source->transfers) && (dt->source->seat->selection_source != dt->source))
85 comp_data_device_source_reader_clear(dt->source);
86 free(dt);
87 }
88
89 return ECORE_CALLBACK_RENEW;
90}
91
92static void
93x11_send_send(Comp_Data_Device_Source *source, const char* mime_type, int32_t fd, Comp_Data_Device_Offer_Type type)
94{
95 Ecore_X_Atom t, sel = ECORE_X_ATOM_SELECTION_CLIPBOARD;
96 Comp_Data_Device_Transfer *dt;
97 Ecore_Window win;
98 win = ecore_evas_window_get(ecore_evas_ecore_evas_get(source->seat->c->evas));
99 if (type == COMP_DATA_DEVICE_OFFER_TYPE_DND)
100 sel = ECORE_X_ATOM_SELECTION_XDND;
101
102 if (eina_streq(mime_type, WL_TEXT_STR))
103 t = string_atom;
104 else
105 t = ecore_x_atom_get(mime_type);
106
107 dt = calloc(1, sizeof(Comp_Data_Device_Transfer));
108 dt->type = type;
109 dt->fdh = ecore_main_fd_handler_add(fd, 0, x11_offer_write, dt, NULL, NULL);
110 dt->source = source;
111 dt->mime_type = eina_stringshare_add(ecore_x_atom_name_get(t));
112 dt->source->transfers = eina_inlist_append(dt->source->transfers, EINA_INLIST_GET(dt));
113 xconvertselection(ecore_x_display_get(), sel, t, comp_dnd_atom, win, ecore_x_current_time_get());
114}
115
116static Eina_Bool
117x11_fixes_selection_notify(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Fixes_Selection_Notify *ev)
118{
119 Ecore_X_Window win;
120 Eina_List *l;
121 Comp *c;
122 Comp_Seat *s;
123
124 EINA_LIST_FOREACH(comps, l, c)
125 {
126 win = ecore_evas_window_get(ecore_evas_ecore_evas_get(c->evas));
127 if (ev->owner == win)
128 return ECORE_CALLBACK_RENEW;
129 c->x11_selection = 0;
130 }
131 if (ev->atom == ECORE_X_ATOM_SELECTION_CLIPBOARD)
132 {
133 EINA_LIST_FOREACH(comps, l, c)
134 EINA_INLIST_FOREACH(c->seats, s)
135 {
136 s->x11_selection_owner = ev->owner;
137 if (ev->owner) s->selection_source = NULL;
138 }
139 if (ev->owner)
140 {
141 xconvertselection(ecore_x_display_get(), ECORE_X_ATOM_SELECTION_CLIPBOARD,
142 ECORE_X_ATOM_SELECTION_TARGETS, comp_dnd_atom, ev->win, 0);
143 }
144 }
145 return ECORE_CALLBACK_RENEW;
146}
147
148static Eina_Bool
149x11_selection_notify(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Selection_Notify *ev)
150{
151 Ecore_X_Selection_Data *sd;
152 Eina_List *l, *lc = NULL;
153 Comp *c;
154 Comp_Seat *s;
155 Comp_Data_Device_Transfer *dt;
156 Eina_Binbuf *buf = NULL;
157
158 if ((ev->selection != ECORE_X_SELECTION_XDND) && (ev->selection != ECORE_X_SELECTION_CLIPBOARD))
159 {
160 EINA_LIST_FOREACH(comps, l, c)
161 EINA_INLIST_FOREACH(c->seats, s)
162 {
163 ecore_evas_free(s->drag.proxy_win);
164 s->drag.proxy_win = NULL;
165 }
166 return ECORE_CALLBACK_RENEW;
167 }
168 EINA_LIST_FOREACH(comps, l, c)
169 {
170 Ecore_X_Window win = ecore_evas_window_get(ecore_evas_ecore_evas_get(c->evas));
171 if (win == ev->win) lc = eina_list_append(lc, c);
172 }
173 if (ev->selection == ECORE_X_SELECTION_CLIPBOARD)
174 {
175 if (eina_streq(ev->target, "TARGETS"))
176 {
177 Ecore_X_Selection_Data_Targets *tgs = ev->data;
178 int i, j;
179 const char **types;
180
181 types = alloca((tgs->num_targets + 1) * sizeof(void*));
182 for (i = j = 0; i < tgs->num_targets; i++)
183 if (tgs->targets[i])
184 types[j++] = tgs->targets[i];
185 types[j] = NULL;
186 EINA_LIST_FREE(lc, c)
187 EINA_INLIST_FOREACH(c->seats, s)
188 s->client_selection_serial = ecore_wl2_dnd_selection_set(s->client_seat, (const char**)types);
189 return ECORE_CALLBACK_RENEW;
190 }
191 }
192 if (ev->property != comp_dnd_atom) return ECORE_CALLBACK_RENEW;
193 EINA_LIST_FREE(lc, c)
194 {
195 EINA_INLIST_FOREACH(c->seats, s)
196 {
197
198 if (s->drag.source && s->drag.source->transfers &&
199 (ev->selection == ECORE_X_SELECTION_XDND))
200 {
201 EINA_INLIST_FOREACH(s->drag.source->transfers, dt)
202 if (eina_streq(ev->target, dt->mime_type))
203 {
204 if (!s->drag.source->reader_data)
205 s->drag.source->reader_data = eina_binbuf_new();
206 buf = s->drag.source->reader_data;
207 break;
208 }
209 }
210 else if (s->selection_source && s->selection_source->transfers &&
211 (ev->selection == ECORE_X_SELECTION_CLIPBOARD))
212 {
213 EINA_INLIST_FOREACH(s->selection_source->transfers, dt)
214 if (eina_streq(ev->target, dt->mime_type))
215 {
216 if (!s->selection_source->reader_data)
217 s->selection_source->reader_data = eina_binbuf_new();
218 buf = s->selection_source->reader_data;
219 break;
220 }
221 }
222 if (buf) break;
223 }
224 if (buf) break;
225 }
226 eina_list_free(lc);
227
228 if (!buf) return ECORE_CALLBACK_RENEW;
229 sd = ev->data;
230 eina_binbuf_append_length(buf, sd->data, sd->length);
231 ecore_main_fd_handler_active_set(dt->fdh, ECORE_FD_WRITE | ECORE_FD_ERROR);
232
233 return ECORE_CALLBACK_RENEW;
234}
235
236static Eina_Bool
237x11_pipe_read(void *data, Ecore_Fd_Handler *fdh)
238{
239 Pipe *p = data;
240 ssize_t len;
241 unsigned char *buf;
242
243 buf = malloc(INCR_CHUNK_SIZE);
244 len = read(ecore_main_fd_handler_fd_get(fdh), (void*)buf, INCR_CHUNK_SIZE);
245 if (len < 0)
246 {
247 free(buf);
248 _incr_update(p, 0);
249 eina_hash_del_by_key(pipes, &p->win);
250 }
251 if (len == INCR_CHUNK_SIZE)
252 {
253 p->buf = eina_binbuf_manage_new(buf, len, 0);
254 if (p->incr)
255 _incr_upload(p);
256 else
257 {
258 unsigned long size = INCR_CHUNK_SIZE;
259
260 p->incr = 1;
261 ecore_x_window_prop_property_set(p->win, p->atom, incr_atom, 32, &size, 1);
262 _incr_update(p, 1);
263 }
264 ecore_main_fd_handler_active_set(p->fdh, 0);
265 return ECORE_CALLBACK_RENEW;
266 }
267 if (len)
268 p->buf = eina_binbuf_manage_new(buf, len, 0);
269 _incr_upload(p);
270 if (p->incr)
271 ecore_main_fd_handler_active_set(p->fdh, 0);
272 else
273 {
274 _incr_update(p, 1);
275 eina_hash_del_by_key(pipes, &p->win);
276 }
277 return ECORE_CALLBACK_RENEW;
278}
279
280static Eina_Bool
281x11_selection_request(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Selection_Request *ev)
282{
283 Comp_Data_Device_Source *source;
284 Eina_List *l;
285 Comp *c;
286 const char *type;
287 Comp_Seat *s = NULL;
288
289 EINA_LIST_FOREACH(comps, l, c)
290 {
291 Ecore_Window win = ecore_evas_window_get(ecore_evas_ecore_evas_get(c->evas));
292 if (c->x11_selection || ((ev->owner == win) && (ev->selection == ECORE_X_ATOM_SELECTION_XDND)))
293 {
294 s = EINA_INLIST_CONTAINER_GET(c->seats, Comp_Seat);
295 break;
296 }
297 }
298 if (!s) return ECORE_CALLBACK_RENEW;
299 if (s->drag.source)
300 source = s->drag.source;
301 else if (s->selection_source)
302 source = s->selection_source;
303 else
304 return ECORE_CALLBACK_RENEW;
305
306 if (ev->target == ECORE_X_ATOM_SELECTION_TARGETS)
307 {
308 Ecore_X_Atom *atoms;
309 int i = 0;
310
311 atoms = alloca((2 + eina_list_count(source->mime_types)) * sizeof(void*));
312 EINA_LIST_FOREACH(source->mime_types, l, type)
313 atoms[i++] = ecore_x_atom_get(type);
314 atoms[i++] = timestamp_atom;
315 atoms[i++] = ECORE_X_ATOM_SELECTION_TARGETS;
316 ecore_x_window_prop_property_set(ev->requestor, ev->property, ECORE_X_ATOM_ATOM, 32, atoms, i);
317 ecore_x_selection_notify_send(ev->requestor, ev->selection, ev->target, ev->property, 0);
318 }
319 else if (ev->target == timestamp_atom)
320 {
321 Ecore_X_Time timestamp;
322
323 timestamp = ecore_x_current_time_get();
324 ecore_x_window_prop_property_set(ev->requestor, ev->property, int_atom, 32, (void*)&timestamp, 1);
325 ecore_x_selection_notify_send(ev->requestor, ev->selection, ev->target, ev->property, 0);
326 }
327 else
328 {
329 const char *name;
330 Pipe *p;
331
332 name = ecore_x_atom_name_get(ev->target);
333 EINA_LIST_FOREACH(source->mime_types, l, type)
334 if (eina_streq(name, type))
335 {
336 int fds[2];
337
338 p = calloc(1, sizeof(Pipe));
339 socketpair(AF_UNIX, (SOCK_STREAM | SOCK_CLOEXEC), 0, fds);
340 fcntl(fds[0], F_SETFL, O_NONBLOCK);
341 p->fdh = ecore_main_fd_handler_add(fds[0], ECORE_FD_READ, x11_pipe_read, p, NULL, NULL);
342 p->win = ev->requestor;
343 p->source = source;
344 wl_data_source_send_send(source->res, type, fds[1]);
345 close(fds[1]);
346 p->atom = ev->target;
347 p->selection = ev->selection;
348 p->property = ev->property;
349 ecore_x_window_sniff(ev->requestor);
350 eina_hash_add(pipes, &p->win, p);
351 break;
352 }
353 }
354 return ECORE_CALLBACK_RENEW;
355}
356
357static Eina_Bool
358x11_property(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Window_Property *ev)
359{
360 Pipe *p;
361
362 if (!ev->state) return ECORE_CALLBACK_RENEW;
363 p = eina_hash_find(pipes, &ev->win);
364 if (!p) return ECORE_CALLBACK_RENEW;
365 /* FIXME: WHO FORGOT THE FUCKING STATE FLAG???? */
366 ecore_main_fd_handler_active_set(p->fdh, ECORE_FD_READ);
367 return ECORE_CALLBACK_RENEW;
368}
369
370static Eina_Bool
371x11_dnd_enter(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Xdnd_Enter *ev)
372{
373 Comp_Seat *s;
374 Comp *c;
375 Eina_List *l;
376 const char **types;
377 int i;
378
379 types = alloca(sizeof(void*) * (ev->num_types + 1));
380 for (i = 0; i < ev->num_types; i++)
381 types[i] = ev->types[i];
382 types[ev->num_types] = NULL;
383
384 EINA_LIST_FOREACH(comps, l, c)
385 {
386 Ecore_Window win = ecore_evas_window_get(ecore_evas_ecore_evas_get(c->evas));
387 if (win != ev->win) continue;
388 EINA_INLIST_FOREACH(c->seats, s)
389 {
390 if (s->drag.x11_owner == ev->source) continue;
391 s->drag.x11_owner = ev->source;
392 for (i = 0; i < ev->num_types; i++)
393 s->drag.x11_types = eina_list_append(s->drag.x11_types, eina_stringshare_add(ev->types[i]));
394 ecore_wl2_dnd_drag_types_set(s->client_seat, (const char**)types);
395 ecore_wl2_dnd_set_actions(s->client_seat);
396 }
397 }
398
399 return ECORE_CALLBACK_RENEW;
400}
401
402static Eina_Bool
403x11_dnd_leave(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Xdnd_Leave *ev)
404{
405 Comp_Seat *s;
406 Comp *c;
407 Eina_List *l;
408
409 EINA_LIST_FOREACH(comps, l, c)
410 {
411 Ecore_Window win = ecore_evas_window_get(ecore_evas_ecore_evas_get(c->evas));
412 if (win != ev->win) continue;
413 EINA_INLIST_FOREACH(c->seats, s)
414 {
415 if (s->drag.x11_owner == win) continue; //self drag
416 if (s->drag.source)
417 wl_data_source_send_cancelled(s->drag.source->res);
418 if (s->client_seat)
419 ecore_wl2_dnd_drag_end(s->client_seat);
420 s->drag.source = NULL;
421 s->drag.res = NULL;
422 s->drag.enter = NULL;
423 s->drag.x11_owner = 0;
424 }
425 }
426 return ECORE_CALLBACK_RENEW;
427}
428
429static Eina_Bool
430x11_dnd_position(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Xdnd_Position *ev)
431{
432 Comp *c;
433 Eina_List *l;
434 Comp_Seat *s;
435
436 EINA_LIST_FOREACH(comps, l, c)
437 {
438 int x, y, cx, cy, cw, ch;
439 Ecore_Window win = ecore_evas_window_get(ecore_evas_ecore_evas_get(c->evas));
440 if (win != ev->win) continue;
441 ecore_evas_geometry_get(ecore_evas_ecore_evas_get(c->evas), &x, &y, NULL, NULL);
442 evas_object_geometry_get(c->obj, &cx, &cy, &cw, &ch);
443 if (!COORDS_INSIDE(ev->position.x, ev->position.y, x + cx, y + cy, cw, ch)) continue;
444 EINA_INLIST_FOREACH(c->seats, s)
445 dnd_motion(s, ev->position.x - x - cx, ev->position.y - y - cy);
446 }
447 return ECORE_CALLBACK_RENEW;
448}
449
450static Eina_Bool
451x11_dnd_drop(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Xdnd_Drop *ev)
452{
453 Comp *c;
454 Eina_List *l;
455 Comp_Seat *s;
456
457 EINA_LIST_FOREACH(comps, l, c)
458 {
459 int x, y, cx, cy, cw, ch;
460 Ecore_Window win = ecore_evas_window_get(ecore_evas_ecore_evas_get(c->evas));
461 if (win != ev->win) continue;
462 ecore_evas_geometry_get(ecore_evas_ecore_evas_get(c->evas), &x, &y, NULL, NULL);
463 evas_object_geometry_get(c->obj, &cx, &cy, &cw, &ch);
464 if (!COORDS_INSIDE(ev->position.x, ev->position.y, x + cx, y + cy, cw, ch)) continue;
465 EINA_INLIST_FOREACH(c->seats, s)
466 drag_grab_button(s, 0, s->drag.id, WL_POINTER_BUTTON_STATE_RELEASED);
467 }
468 return ECORE_CALLBACK_RENEW;
469}
470
471static Eina_Bool
472x11_dnd_finished(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Xdnd_Finished *ev)
473{
474 Comp *c;
475 Eina_List *l;
476 Comp_Seat *s;
477
478 EINA_LIST_FOREACH(comps, l, c)
479 {
480 Ecore_Window win = ecore_evas_window_get(ecore_evas_ecore_evas_get(c->evas));
481 if (win != ev->win) continue;
482 EINA_INLIST_FOREACH(c->seats, s)
483 {
484 Comp_Data_Device_Source *source = s->drag.source;
485 if (s->drag.x11_owner != win) continue;
486 if (s->drag.source) s->drag.source->accepted = ev->completed;
487 drag_grab_button(s, 0, s->drag.id, WL_POINTER_BUTTON_STATE_RELEASED);
488 data_source_notify_finish(source);
489 }
490 }
491 return ECORE_CALLBACK_RENEW;
492}
493
494static Eina_Bool
495x11_dnd_mouse_up(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Button *ev)
496{
497 Comp *c;
498 Eina_List *l;
499 Comp_Seat *s;
500
501 EINA_LIST_FOREACH(comps, l, c)
502 {
503 Ecore_Window win = ecore_evas_window_get(ecore_evas_ecore_evas_get(c->evas));
504 if (win != ev->event_window) continue;
505 EINA_INLIST_FOREACH(c->seats, s)
506 if (s->drag.id == ev->buttons)
507 {
508 ecore_x_dnd_self_drop();
509 ecore_x_pointer_ungrab();
510 ecore_evas_free(s->drag.proxy_win);
511 }
512 }
513 return ECORE_CALLBACK_RENEW;
514}
515
516static void
517x11_dnd_move(void *data, Ecore_X_Xdnd_Position *pos)
518{
519 evas_object_move(data, pos->position.x, pos->position.y);
520}
521
522static void
523x11_init(void)
524{
525 Ecore_Event_Handler *h;
526
527 ecore_x_fixes_selection_notification_request(ecore_x_atom_get("CLIPBOARD"));
528 ecore_x_fixes_selection_notification_request(ECORE_X_ATOM_SELECTION_XDND);
529 h = ecore_event_handler_add(ECORE_X_EVENT_FIXES_SELECTION_NOTIFY, (Ecore_Event_Handler_Cb)x11_fixes_selection_notify, NULL);
530 handlers = eina_list_append(handlers, h);
531 h = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, (Ecore_Event_Handler_Cb)x11_selection_notify, NULL);
532 handlers = eina_list_append(handlers, h);
533 h = ecore_event_handler_add(ECORE_X_EVENT_SELECTION_REQUEST, (Ecore_Event_Handler_Cb)x11_selection_request, NULL);
534 handlers = eina_list_append(handlers, h);
535 h = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, (Ecore_Event_Handler_Cb)x11_property, NULL);
536 handlers = eina_list_append(handlers, h);
537 h = ecore_event_handler_add(ECORE_X_EVENT_XDND_ENTER, (Ecore_Event_Handler_Cb)x11_dnd_enter, NULL);
538 handlers = eina_list_append(handlers, h);
539 h = ecore_event_handler_add(ECORE_X_EVENT_XDND_LEAVE, (Ecore_Event_Handler_Cb)x11_dnd_leave, NULL);
540 handlers = eina_list_append(handlers, h);
541 h = ecore_event_handler_add(ECORE_X_EVENT_XDND_POSITION, (Ecore_Event_Handler_Cb)x11_dnd_position, NULL);
542 handlers = eina_list_append(handlers, h);
543 h = ecore_event_handler_add(ECORE_X_EVENT_XDND_DROP, (Ecore_Event_Handler_Cb)x11_dnd_drop, NULL);
544 handlers = eina_list_append(handlers, h);
545 h = ecore_event_handler_add(ECORE_X_EVENT_XDND_FINISHED, (Ecore_Event_Handler_Cb)x11_dnd_finished, NULL);
546 handlers = eina_list_append(handlers, h);
547 h = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP, (Ecore_Event_Handler_Cb)x11_dnd_mouse_up, NULL);
548 handlers = eina_list_append(handlers, h);
549 xconvertselection = dlsym(NULL, "XConvertSelection");
550 string_atom = ecore_x_atom_get("UTF8_STRING");
551 timestamp_atom = ecore_x_atom_get("TIMESTAMP");
552 int_atom = ecore_x_atom_get("INTEGER");
553 incr_atom = ecore_x_atom_get("TIMESTAMP");
554 comp_dnd_atom = ecore_x_atom_get("SIRCMPWIDG_ATOM");
555 pipes = eina_hash_int32_new((Eina_Free_Cb)_pipe_free);
556}
557
558static void
559x11_shutdown(void)
560{
561 eina_hash_free(pipes);
562 pipes = NULL;
563}