54
52
struct input *input;
55
int x_offset, y_offset;
56
const char *mime_type;
60
62
struct wl_array types;
61
63
const char *drag_type;
66
69
cairo_surface_t *surface;
74
struct dnd_flower_message {
75
int seed, x_offset, y_offset;
70
79
static const int item_width = 64;
71
80
static const int item_height = 64;
72
81
static const int item_padding = 16;
74
83
static struct item *
75
item_create(struct display *display, int x, int y)
84
item_create(struct display *display, int x, int y, int seed)
89
item = malloc(sizeof *item);
94
gettimeofday(&tv, NULL);
95
item->seed = seed ? seed : tv.tv_usec;
77
98
const int petal_count = 3 + random() % 5;
78
99
const double r1 = 20 + random() % 10;
79
100
const double r2 = 5 + random() % 12;
85
106
double t, dt = 2 * M_PI / (petal_count * 2);
86
107
double x1, y1, x2, y2, x3, y3;
87
108
struct rectangle rect;
90
item = malloc(sizeof *item);
94
111
rect.width = item_width;
95
112
rect.height = item_height;
153
170
dnd_draw(struct dnd *dnd)
155
struct rectangle rectangle;
172
struct rectangle allocation;
157
174
cairo_surface_t *wsurface, *surface;
160
177
window_draw(dnd->window);
162
window_get_child_rectangle(dnd->window, &rectangle);
179
window_get_child_allocation(dnd->window, &allocation);
164
181
wsurface = window_get_surface(dnd->window);
165
182
surface = cairo_surface_create_similar(wsurface,
166
183
CAIRO_CONTENT_COLOR_ALPHA,
169
186
cairo_surface_destroy(wsurface);
171
188
cr = cairo_create(surface);
185
202
cairo_destroy(cr);
187
window_copy_surface(dnd->window, &rectangle, surface);
204
window_copy_surface(dnd->window, &allocation, surface);
188
205
cairo_surface_destroy(surface);
189
206
window_flush(dnd->window);
206
223
window_schedule_redraw(dnd->window);
227
dnd_offer_destroy(struct dnd_offer *dnd_offer)
229
dnd_offer->refcount--;
230
if (dnd_offer->refcount == 0) {
231
wl_array_release(&dnd_offer->types);
237
dnd_add_item(struct dnd *dnd, struct item *item)
241
for (i = 0; i < ARRAY_LENGTH(dnd->items); i++) {
242
if (dnd->items[i] == 0) {
243
dnd->items[i] = item;
209
250
static struct item *
210
251
dnd_get_item(struct dnd *dnd, int32_t x, int32_t y)
212
253
struct item *item;
213
struct rectangle rectangle;
254
struct rectangle allocation;
216
window_get_child_rectangle(dnd->window, &rectangle);
257
window_get_child_allocation(dnd->window, &allocation);
221
262
for (i = 0; i < ARRAY_LENGTH(dnd->items); i++) {
222
263
item = dnd->items[i];
242
283
fprintf(stderr, "target %s\n", mime_type);
243
284
device = input_get_input_device(dnd_drag->input);
285
dnd_drag->mime_type = mime_type;
245
287
surface = dnd_drag->opaque;
255
297
drag_finish(void *data, struct wl_drag *drag, int fd)
257
299
struct dnd_drag *dnd_drag = data;
258
char text[] = "[drop data]";
260
fprintf(stderr, "got 'finish', fd %d, sending message\n", fd);
262
write(fd, text, sizeof text);
301
if (!dnd_drag->mime_type) {
302
dnd_add_item(dnd_drag->dnd, dnd_drag->item);
303
window_schedule_redraw(dnd_drag->dnd->window);
307
struct dnd_flower_message dnd_flower_message;
310
dnd_flower_message.seed = dnd_drag->item->seed;
312
dnd_flower_message.x_offset = dnd_drag->x_offset;
313
dnd_flower_message.y_offset = dnd_drag->y_offset;
315
fprintf(stderr, "got 'finish', fd %d, sending dnd_flower_message\n", fd);
317
write(fd, &dnd_flower_message, sizeof dnd_flower_message);
265
320
/* The 'finish' event marks the end of the session on the drag
266
321
* source side and we need to clean up the drag object created
267
322
* and the local state. */
268
323
wl_drag_destroy(drag);
325
/* Destroy the item that has been dragged out */
326
cairo_surface_destroy(dnd_drag->item->surface);
327
free(dnd_drag->item);
269
329
cairo_surface_destroy(dnd_drag->translucent);
270
330
cairo_surface_destroy(dnd_drag->opaque);
335
drag_reject(void *data, struct wl_drag *drag)
337
struct dnd_drag *dnd_drag = data;
339
dnd_add_item(dnd_drag->dnd, dnd_drag->item);
340
window_schedule_redraw(dnd_drag->dnd->window);
274
343
static const struct wl_drag_listener drag_listener = {
307
377
fprintf(stderr, "pointer focus NULL, session over\n");
308
wl_array_release(&dnd_offer->types);
310
378
wl_drag_offer_destroy(offer);
379
dnd_offer_destroy(dnd_offer);
321
390
dnd_offer->dnd = window_get_user_data(window);
323
392
if (!dnd_get_item(dnd_offer->dnd, surface_x, surface_y)) {
324
wl_drag_offer_accept(offer, time, "text/plain");
325
dnd_offer->drag_type = "text/plain";
393
wl_drag_offer_accept(offer, time, "application/x-wayland-dnd-flower");
394
dnd_offer->drag_type = "application/x-wayland-dnd-flower";
395
dnd_offer->x = surface_x;
396
dnd_offer->y = surface_y;
327
398
wl_drag_offer_accept(offer, time, NULL);
328
399
dnd_offer->drag_type = NULL;
335
406
int32_t x, int32_t y, int32_t surface_x, int32_t surface_y)
337
408
struct dnd_offer *dnd_offer = data;
338
struct dnd *dnd = dnd_offer->dnd;
340
if (!dnd_get_item(dnd, surface_x, surface_y)) {
410
if (!dnd_get_item(dnd_offer->dnd, surface_x, surface_y)) {
341
411
fprintf(stderr, "drag offer motion %d, %d, accepting\n",
342
412
surface_x, surface_y);
343
wl_drag_offer_accept(offer, time, "text/plain");
344
dnd_offer->drag_type = "text/plain";
413
wl_drag_offer_accept(offer, time, "application/x-wayland-dnd-flower");
414
dnd_offer->drag_type = "application/x-wayland-dnd-flower";
415
dnd_offer->x = surface_x;
416
dnd_offer->y = surface_y;
346
418
fprintf(stderr, "drag offer motion %d, %d, declining\n",
347
419
surface_x, surface_y);
354
426
drop_io_func(GIOChannel *source, GIOCondition condition, gpointer data)
356
428
struct dnd_offer *dnd_offer = data;
429
struct dnd *dnd = dnd_offer->dnd;
430
struct dnd_flower_message dnd_flower_message;
359
432
unsigned int len;
362
g_io_channel_read_chars(source, buffer, sizeof buffer, &len, &err);
363
fprintf(stderr, "read %d bytes: %s\n", len, buffer);
364
435
fd = g_io_channel_unix_get_fd(source);
436
len = read(fd, &dnd_flower_message, sizeof dnd_flower_message);
437
fprintf(stderr, "read %d bytes\n", len);
366
440
g_source_remove(dnd_offer->tag);
368
442
g_io_channel_unref(source);
444
item = item_create(dnd->display,
445
dnd_offer->x - dnd_flower_message.x_offset - 26,
446
dnd_offer->y - dnd_flower_message.y_offset - 66,
447
dnd_flower_message.seed);
449
dnd_add_item(dnd, item);
450
window_schedule_redraw(dnd->window);
452
dnd_offer_destroy(dnd_offer);
380
464
if (!dnd_offer->drag_type) {
381
465
fprintf(stderr, "got 'drop', but no target\n");
382
/* FIXME: Should send response so compositor and
383
* source knows it's over. Can't send -1 to indicate
384
* 'no target' though becauses of the way fd passing
385
* currently works. */
466
wl_drag_offer_reject(offer);
389
470
fprintf(stderr, "got 'drop', sending write end of pipe\n");
472
dnd_offer->refcount++;
392
474
wl_drag_offer_receive(offer, p[1]);
475
559
struct dnd *dnd = data;
477
561
struct item *item;
478
struct rectangle rectangle;
562
struct rectangle allocation;
479
563
struct dnd_drag *dnd_drag;
564
struct wl_drag *drag;
481
window_get_child_rectangle(dnd->window, &rectangle);
567
window_get_child_allocation(dnd->window, &allocation);
482
568
input_get_position(input, &x, &y);
483
569
item = dnd_get_item(dnd, x, y);
487
573
if (item && state == 1) {
488
574
fprintf(stderr, "start drag, item %p\n", item);
491
577
dnd_drag->dnd = dnd;
492
578
dnd_drag->input = input;
493
579
dnd_drag->time = time;
580
dnd_drag->item = item;
581
dnd_drag->x_offset = x - item->x;
582
dnd_drag->y_offset = y - item->y;
584
for (i = 0; i < ARRAY_LENGTH(dnd->items); i++) {
585
if (item == dnd->items[i]){
495
591
dnd_drag->opaque =
496
592
create_drag_cursor(dnd_drag, item, x, y, 1);
497
593
dnd_drag->translucent =
498
594
create_drag_cursor(dnd_drag, item, x, y, 0.2);
500
window_start_drag(window, input, time,
501
&drag_listener, dnd_drag);
596
drag = window_create_drag(window);
597
wl_drag_offer(drag, "application/x-wayland-dnd-flower");
598
window_activate_drag(drag, window, input, time);
599
wl_drag_add_listener(drag, &drag_listener, dnd_drag);
600
window_schedule_redraw(dnd->window);
535
634
title = g_strdup_printf("Wayland Drag and Drop Demo");
537
dnd->window = window_create(display, title, 100, 100, 500, 400);
636
dnd->window = window_create(display, title, 500, 400);
538
637
dnd->display = display;
542
641
x = (i % 4) * (item_width + item_padding) + item_padding;
543
642
y = (i / 4) * (item_height + item_padding) + item_padding;
544
643
if ((i ^ (i >> 2)) & 1)
545
dnd->items[i] = item_create(display, x, y);
644
dnd->items[i] = item_create(display, x, y, 0);
547
646
dnd->items[i] = NULL;
557
656
window_set_motion_handler(dnd->window,
558
657
dnd_motion_handler);
560
rectangle.width = 4 * (item_width + item_padding) + item_padding;
561
rectangle.height = 4 * (item_height + item_padding) + item_padding;
562
window_set_child_size(dnd->window, &rectangle);
659
width = 4 * (item_width + item_padding) + item_padding;
660
height = 4 * (item_height + item_padding) + item_padding;
661
window_set_child_size(dnd->window, width, height);