diff options
author | Mike Blumenkrantz <zmike@osg.samsung.com> | 2017-06-30 14:59:21 -0400 |
---|---|---|
committer | Mike Blumenkrantz <zmike@osg.samsung.com> | 2017-06-30 14:59:55 -0400 |
commit | c2fde93c9ef1108c0809a538cf2ec482ed8369a9 (patch) | |
tree | d9879e4ebea4d25cda1a6cc1268461ad0d669c3b /src/lib/efl_wl/x11.x | |
parent | 3775a9645da7e92599babccfe8454304cec367b7 (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 'src/lib/efl_wl/x11.x')
-rw-r--r-- | src/lib/efl_wl/x11.x | 563 |
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 | |||
4 | static void (*xconvertselection)(Ecore_X_Display *, Ecore_X_Atom, Ecore_X_Atom, Ecore_X_Atom, Ecore_X_Window, Ecore_X_Time); | ||
5 | static Ecore_X_Atom string_atom; | ||
6 | static Ecore_X_Atom comp_dnd_atom; | ||
7 | static Ecore_X_Atom timestamp_atom; | ||
8 | static Ecore_X_Atom incr_atom; | ||
9 | static Ecore_X_Atom int_atom; | ||
10 | |||
11 | static Eina_Hash *pipes; | ||
12 | |||
13 | typedef 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 | |||
25 | static 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 | |||
34 | static 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 | |||
40 | static 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 | |||
52 | static Eina_Bool | ||
53 | x11_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 | |||
92 | static void | ||
93 | x11_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 | |||
116 | static Eina_Bool | ||
117 | x11_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 | |||
148 | static Eina_Bool | ||
149 | x11_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 | |||
236 | static Eina_Bool | ||
237 | x11_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 | |||
280 | static Eina_Bool | ||
281 | x11_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*)×tamp, 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 | |||
357 | static Eina_Bool | ||
358 | x11_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 | |||
370 | static Eina_Bool | ||
371 | x11_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 | |||
402 | static Eina_Bool | ||
403 | x11_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 | |||
429 | static Eina_Bool | ||
430 | x11_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 | |||
450 | static Eina_Bool | ||
451 | x11_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 | |||
471 | static Eina_Bool | ||
472 | x11_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 | |||
494 | static Eina_Bool | ||
495 | x11_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 | |||
516 | static void | ||
517 | x11_dnd_move(void *data, Ecore_X_Xdnd_Position *pos) | ||
518 | { | ||
519 | evas_object_move(data, pos->position.x, pos->position.y); | ||
520 | } | ||
521 | |||
522 | static void | ||
523 | x11_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 | |||
558 | static void | ||
559 | x11_shutdown(void) | ||
560 | { | ||
561 | eina_hash_free(pipes); | ||
562 | pipes = NULL; | ||
563 | } | ||