summaryrefslogtreecommitdiff
path: root/src/lib/ecore_wayland/ecore_wl_dnd.c
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2012-12-02 22:35:45 +0000
committerVincent Torri <vincent.torri@gmail.com>2012-12-02 22:35:45 +0000
commit7d6010b12c47a20e492da808e3192c3f87dab619 (patch)
tree26c6fd189e046a76560c0bc740b85f4d767ae399 /src/lib/ecore_wayland/ecore_wl_dnd.c
parent53fc441d5475155965d92da89502fe4634a561b2 (diff)
merge: add escape ecore, fix several bugs
SVN revision: 79995
Diffstat (limited to 'src/lib/ecore_wayland/ecore_wl_dnd.c')
-rw-r--r--src/lib/ecore_wayland/ecore_wl_dnd.c485
1 files changed, 485 insertions, 0 deletions
diff --git a/src/lib/ecore_wayland/ecore_wl_dnd.c b/src/lib/ecore_wayland/ecore_wl_dnd.c
new file mode 100644
index 0000000000..403e3b9f6b
--- /dev/null
+++ b/src/lib/ecore_wayland/ecore_wl_dnd.c
@@ -0,0 +1,485 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <fcntl.h>
6#include <sys/epoll.h>
7#include "ecore_wl_private.h"
8
9struct _dnd_task
10{
11 void *data;
12 Ecore_Fd_Cb cb;
13};
14
15struct _dnd_read_ctx
16{
17 int epoll_fd;
18 struct epoll_event *ep;
19};
20
21/* local function prototypes */
22static void _ecore_wl_dnd_offer(void *data, struct wl_data_offer *wl_data_offer EINA_UNUSED, const char *type);
23static void _ecore_wl_dnd_cb_enter_free(void *data EINA_UNUSED, void *event);
24
25static void _ecore_wl_dnd_data_source_target(void *data, struct wl_data_source *source, const char *mime_type);
26static void _ecore_wl_dnd_data_source_send(void *data, struct wl_data_source *source, const char *mime_type, int32_t fd);
27static void _ecore_wl_dnd_data_source_cancelled(void *data, struct wl_data_source *source);
28static void _ecore_wl_dnd_source_receive_data(Ecore_Wl_Dnd_Source *source, const char *type);
29
30/* wayland listeners */
31static const struct wl_data_offer_listener _ecore_wl_data_offer_listener =
32{
33 _ecore_wl_dnd_offer,
34};
35
36static const struct wl_data_source_listener _ecore_wl_data_source_listener =
37{
38 _ecore_wl_dnd_data_source_target,
39 _ecore_wl_dnd_data_source_send,
40 _ecore_wl_dnd_data_source_cancelled
41};
42
43extern Ecore_Wl_Dnd *glb_dnd;
44
45EAPI Ecore_Wl_Dnd *
46ecore_wl_dnd_get()
47{
48 return glb_dnd;
49}
50
51EAPI Eina_Bool
52ecore_wl_dnd_start_drag(Ecore_Wl_Dnd *dnd EINA_UNUSED)
53{
54 //TODO:
55 return EINA_TRUE;
56}
57
58EAPI Eina_Bool
59ecore_wl_dnd_set_selection(Ecore_Wl_Dnd *dnd, const char **types_offered)
60{
61 char **p;
62 const char **type;
63
64 dnd->data_source = _ecore_wl_create_data_source(dnd->ewd);
65
66 /* free old types */
67 if (dnd->types_offered.data)
68 {
69 wl_array_for_each(p, &dnd->types_offered)
70 free(*p);
71 wl_array_release(&dnd->types_offered);
72 wl_array_init(&dnd->types_offered);
73 }
74
75 for (type = types_offered; *type; type++)
76 {
77 p = wl_array_add(&dnd->types_offered, sizeof(*p));
78 *p = strdup(*type);
79 wl_data_source_offer(dnd->data_source, *p);
80 }
81
82 wl_data_source_add_listener(dnd->data_source, &_ecore_wl_data_source_listener, dnd);
83
84 _ecore_wl_input_set_selection(dnd->input, dnd->data_source);
85
86 return EINA_TRUE;
87}
88
89EAPI Eina_Bool
90ecore_wl_dnd_get_selection(Ecore_Wl_Dnd *dnd, const char *type)
91{
92 char **p;
93 Ecore_Wl_Input *input;
94
95 input = dnd->input;
96
97 if (!input->selection_source) return EINA_FALSE;
98
99 wl_array_for_each(p, &input->selection_source->types)
100 if (strcmp(type, *p) == 0) break;
101
102 if (!*p) return EINA_FALSE;
103
104 _ecore_wl_dnd_source_receive_data(input->selection_source, type);
105
106 return EINA_TRUE;
107}
108
109EAPI Eina_Bool
110ecore_wl_dnd_selection_has_owner(Ecore_Wl_Dnd *dnd)
111{
112 Ecore_Wl_Input *input;
113
114 input = dnd->input;
115 return (input->selection_source != NULL);
116}
117
118/* local functions */
119static void
120_ecore_wl_dnd_data_source_target(void *data EINA_UNUSED, struct wl_data_source *source EINA_UNUSED, const char *mime_type EINA_UNUSED)
121{
122 //TODO:
123}
124
125static void
126_ecore_wl_dnd_cb_data_source_send_free(void *data EINA_UNUSED, void *event)
127{
128 Ecore_Wl_Event_Data_Source_Send *ev;
129
130 LOGFN(__FILE__, __LINE__, __FUNCTION__);
131
132 if (!(ev = event)) return;
133
134 free(ev->type);
135 free(ev);
136}
137
138static void
139_ecore_wl_dnd_data_source_send(void *data, struct wl_data_source *source EINA_UNUSED, const char *mime_type, int32_t fd)
140{
141 Ecore_Wl_Event_Data_Source_Send *event;
142
143 LOGFN(__FILE__, __LINE__, __FUNCTION__);
144
145 if (!data) return;
146
147 if (!(event = calloc(1, sizeof(Ecore_Wl_Event_Data_Source_Send)))) return;
148
149 event->type = strdup(mime_type);
150 event->fd = fd;
151
152 ecore_event_add(ECORE_WL_EVENT_DATA_SOURCE_SEND, event, _ecore_wl_dnd_cb_data_source_send_free, NULL);
153}
154
155static void
156_ecore_wl_dnd_data_source_cancelled(void *data EINA_UNUSED, struct wl_data_source *source)
157{
158 wl_data_source_destroy(source);
159}
160
161void
162_ecore_wl_dnd_add(Ecore_Wl_Input *input, struct wl_data_device *data_device EINA_UNUSED, struct wl_data_offer *offer)
163{
164 Ecore_Wl_Dnd_Source *source;
165
166 LOGFN(__FILE__, __LINE__, __FUNCTION__);
167
168 if (!(source = malloc(sizeof(Ecore_Wl_Dnd_Source)))) return;
169 wl_array_init(&source->types);
170 source->refcount = 1;
171 source->input = input;
172 source->offer = offer;
173 wl_data_offer_add_listener(source->offer,
174 &_ecore_wl_data_offer_listener, source);
175}
176
177void
178_ecore_wl_dnd_enter(void *data, struct wl_data_device *data_device EINA_UNUSED, unsigned int timestamp EINA_UNUSED, struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y, struct wl_data_offer *offer)
179{
180 Ecore_Wl_Event_Dnd_Enter *event;
181 Ecore_Wl_Input *input;
182 Ecore_Wl_Window *win;
183 char **p;
184
185 LOGFN(__FILE__, __LINE__, __FUNCTION__);
186
187 if ((!(input = data)) || (!offer)) return;
188
189 if (!(input->drag_source = wl_data_offer_get_user_data(offer)))
190 return;
191
192 win = wl_surface_get_user_data(surface);
193// input->pointer_focus = win;
194
195 p = wl_array_add(&input->drag_source->types, sizeof(*p));
196 *p = NULL;
197
198 if (!(event = calloc(1, sizeof(Ecore_Wl_Event_Dnd_Enter)))) return;
199
200 event->win = win->id;
201 if (input->drag_source->input)
202 {
203 if (input->drag_source->input->keyboard_focus)
204 event->source = input->drag_source->input->keyboard_focus->id;
205 }
206
207 event->position.x = wl_fixed_to_int(x);
208 event->position.y = wl_fixed_to_int(y);
209 event->num_types = input->drag_source->types.size;
210 event->types = input->drag_source->types.data;
211
212 ecore_event_add(ECORE_WL_EVENT_DND_ENTER, event,
213 _ecore_wl_dnd_cb_enter_free, NULL);
214}
215
216void
217_ecore_wl_dnd_leave(void *data, struct wl_data_device *data_device EINA_UNUSED)
218{
219 Ecore_Wl_Input *input;
220
221 LOGFN(__FILE__, __LINE__, __FUNCTION__);
222
223 if (!(input = data)) return;
224 /* FIXME: NB: This MAY need to raise a wl_event_dnd_leave for the
225 * source window */
226 _ecore_wl_dnd_del(input->drag_source);
227 input->drag_source = NULL;
228}
229
230void
231_ecore_wl_dnd_motion(void *data, struct wl_data_device *data_device EINA_UNUSED, unsigned int timestamp EINA_UNUSED, wl_fixed_t x, wl_fixed_t y)
232{
233 Ecore_Wl_Event_Dnd_Position *event;
234 Ecore_Wl_Input *input;
235
236 LOGFN(__FILE__, __LINE__, __FUNCTION__);
237
238 if (!(input = data)) return;
239
240 input->sx = wl_fixed_to_int(x);
241 input->sy = wl_fixed_to_int(y);
242
243 if (!(event = calloc(1, sizeof(Ecore_Wl_Event_Dnd_Position)))) return;
244
245 if (input->drag_source)
246 {
247 if (input->drag_source->input)
248 {
249 if (input->drag_source->input->pointer_focus)
250 event->win = input->drag_source->input->pointer_focus->id;
251 if (input->drag_source->input->keyboard_focus)
252 event->source = input->drag_source->input->keyboard_focus->id;
253 }
254 }
255
256 event->position.x = input->sx;
257 event->position.y = input->sy;
258
259 ecore_event_add(ECORE_WL_EVENT_DND_POSITION, event, NULL, NULL);
260}
261
262void
263_ecore_wl_dnd_drop(void *data, struct wl_data_device *data_device EINA_UNUSED)
264{
265 Ecore_Wl_Event_Dnd_Drop *event;
266 Ecore_Wl_Input *input;
267
268 LOGFN(__FILE__, __LINE__, __FUNCTION__);
269
270 if (!(input = data)) return;
271
272 if (!(event = calloc(1, sizeof(Ecore_Wl_Event_Dnd_Drop)))) return;
273
274 if (input->drag_source)
275 {
276 if (input->drag_source->input)
277 {
278 if (input->drag_source->input->pointer_focus)
279 event->win = input->drag_source->input->pointer_focus->id;
280 if (input->drag_source->input->keyboard_focus)
281 event->source = input->drag_source->input->keyboard_focus->id;
282 }
283 }
284
285 event->position.x = input->sx;
286 event->position.y = input->sy;
287
288 ecore_event_add(ECORE_WL_EVENT_DND_DROP, event, NULL, NULL);
289}
290
291void
292_ecore_wl_dnd_selection(void *data, struct wl_data_device *data_device EINA_UNUSED, struct wl_data_offer *offer)
293{
294 Ecore_Wl_Input *input;
295
296 LOGFN(__FILE__, __LINE__, __FUNCTION__);
297
298 if (!(input = data)) return;
299 if (input->selection_source) _ecore_wl_dnd_del(input->selection_source);
300 input->selection_source = NULL;
301 if (offer)
302 {
303 char **p;
304
305 input->selection_source = wl_data_offer_get_user_data(offer);
306 p = wl_array_add(&input->selection_source->types, sizeof(*p));
307 *p = NULL;
308 }
309}
310
311void
312_ecore_wl_dnd_del(Ecore_Wl_Dnd_Source *source)
313{
314 LOGFN(__FILE__, __LINE__, __FUNCTION__);
315
316 if (!source) return;
317 source->refcount--;
318 if (source->refcount == 0)
319 {
320 char **p;
321
322 wl_data_offer_destroy(source->offer);
323 for (p = source->types.data; *p; p++)
324 free(*p);
325 wl_array_release(&source->types);
326 free(source);
327 }
328}
329
330/* local functions */
331static void
332_ecore_wl_dnd_offer(void *data, struct wl_data_offer *wl_data_offer EINA_UNUSED, const char *type)
333{
334 Ecore_Wl_Dnd_Source *source;
335 char **p;
336
337 LOGFN(__FILE__, __LINE__, __FUNCTION__);
338
339 if (!(source = data)) return;
340 p = wl_array_add(&source->types, sizeof(*p));
341 *p = strdup(type);
342}
343
344static void
345_ecore_wl_dnd_cb_enter_free(void *data EINA_UNUSED, void *event)
346{
347 Ecore_Wl_Event_Dnd_Enter *ev;
348
349 LOGFN(__FILE__, __LINE__, __FUNCTION__);
350
351 if (!(ev = event)) return;
352 free(ev);
353}
354
355static void
356_ecore_wl_dnd_cb_selection_data_ready_free(void *data EINA_UNUSED, void *event)
357{
358 Ecore_Wl_Event_Selection_Data_Ready *ev;
359
360 LOGFN(__FILE__, __LINE__, __FUNCTION__);
361
362 if (!(ev = event)) return;
363
364 free(ev->data);
365 free(ev);
366}
367
368static Eina_Bool
369_ecore_wl_dnd_read_data(void *data, Ecore_Fd_Handler *fd_handler EINA_UNUSED)
370{
371 int len;
372 char buffer[4096];
373 Ecore_Wl_Dnd_Source *source;
374 Ecore_Wl_Event_Selection_Data_Ready *event;
375 Eina_Bool ret;
376
377 source = data;
378
379 len = read(source->fd, buffer, sizeof buffer);
380
381 if (!(event = calloc(1, sizeof(Ecore_Wl_Event_Selection_Data_Ready))))
382 return ECORE_CALLBACK_CANCEL;
383
384 if (len <= 0)
385 {
386 close(source->fd);
387 _ecore_wl_dnd_del(source);
388 event->done = EINA_TRUE;
389 event->data = NULL;
390 event->len = 0;
391 ret = ECORE_CALLBACK_CANCEL;
392 }
393 else
394 {
395 event->data = malloc(len + 1);
396 if (!event->data) return ECORE_CALLBACK_CANCEL;
397 strncpy(event->data, buffer, len);
398 event->data[len] = '\0';
399 event->len = len;
400 event->done = EINA_FALSE;
401 ret = ECORE_CALLBACK_RENEW;
402 }
403
404 ecore_event_add(ECORE_WL_EVENT_SELECTION_DATA_READY, event,
405 _ecore_wl_dnd_cb_selection_data_ready_free, NULL);
406 return ret;
407}
408
409
410static Eina_Bool
411_ecore_wl_dnd_idler_cb(void *data)
412{
413 struct _dnd_read_ctx *ctx;
414 struct _dnd_task *task;
415 int count, i;
416
417 ctx = data;
418 count = epoll_wait(ctx->epoll_fd, ctx->ep, 1, 0);
419 for (i = 0; i < count; i++)
420 {
421 task = ctx->ep->data.ptr;
422 if (task->cb(task->data, NULL) == ECORE_CALLBACK_CANCEL)
423 {
424 free(ctx->ep);
425 free(task);
426 free(ctx);
427 return ECORE_CALLBACK_CANCEL;
428 }
429 }
430 return ECORE_CALLBACK_RENEW;
431}
432
433static void
434_ecore_wl_dnd_source_receive_data(Ecore_Wl_Dnd_Source *source, const char *type)
435{
436 int epoll_fd;
437 struct epoll_event *ep = NULL;
438 struct _dnd_task *task = NULL;
439 struct _dnd_read_ctx *read_ctx = NULL;
440 int p[2];
441
442 if (pipe2(p, O_CLOEXEC) == -1)
443 return;
444
445 wl_data_offer_receive(source->offer, type, p[1]);
446 close(p[1]);
447
448 /* Due to http://trac.enlightenment.org/e/ticket/1208,
449 * use epoll and idle handler instead of ecore_main_fd_handler_add() */
450
451 ep = calloc(1, sizeof(struct epoll_event));
452 if (!ep) goto err;
453
454 task = calloc(1, sizeof(struct _dnd_task));
455 if (!task) goto err;
456
457 read_ctx = calloc(1, sizeof(struct _dnd_read_ctx));
458 if (!read_ctx) goto err;
459
460 epoll_fd = epoll_create1(0);
461 if (epoll_fd < 0) goto err;
462
463 task->data = source;
464 task->cb = _ecore_wl_dnd_read_data;
465 ep->events = EPOLLIN;
466 ep->data.ptr = task;
467
468 if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, p[0], ep) < 0) goto err;
469
470 read_ctx->epoll_fd = epoll_fd;
471 read_ctx->ep = ep;
472
473 if (!ecore_idler_add(_ecore_wl_dnd_idler_cb, read_ctx)) goto err;
474
475 source->refcount++;
476 source->fd = p[0];
477 return;
478
479err:
480 if (ep) free(ep);
481 if (task) free(task);
482 if (read_ctx) free(read_ctx);
483 close(p[0]);
484 return;
485}