Make the dnd client actually work.

The dnd client now sends a mime type of
application/x-wayland-dnd-flower instead of text/plain.  The dnd
message is just the position and random seed that lets the drop source
add the flower to its grid.
dev
Joel Teichroeb 14 years ago committed by Kristian Høgsberg
parent d44bc8b8ee
commit 0c007aea35
  1. 145
      clients/dnd.c

@ -53,27 +53,50 @@ struct dnd_drag {
struct dnd *dnd;
struct input *input;
uint32_t time;
struct item *item;
int x_offset, y_offset;
const char *mime_type;
};
struct dnd_offer {
int refcount;
struct dnd *dnd;
struct wl_array types;
const char *drag_type;
uint32_t tag;
int x, y;
};
struct item {
cairo_surface_t *surface;
int seed;
int x, y;
};
struct dnd_flower_message {
int seed, x_offset, y_offset;
};
static const int item_width = 64;
static const int item_height = 64;
static const int item_padding = 16;
static struct item *
item_create(struct display *display, int x, int y)
item_create(struct display *display, int x, int y, int seed)
{
struct item *item;
struct timeval tv;
item = malloc(sizeof *item);
if (item == NULL)
return NULL;
gettimeofday(&tv, NULL);
item->seed = seed ? seed : tv.tv_usec;
srandom(item->seed);
const int petal_count = 3 + random() % 5;
const double r1 = 20 + random() % 10;
const double r2 = 5 + random() % 12;
@ -85,11 +108,7 @@ item_create(struct display *display, int x, int y)
double t, dt = 2 * M_PI / (petal_count * 2);
double x1, y1, x2, y2, x3, y3;
struct rectangle rect;
struct item *item;
item = malloc(sizeof *item);
if (item == NULL)
return NULL;
rect.width = item_width;
rect.height = item_height;
@ -206,6 +225,30 @@ keyboard_focus_handler(struct window *window,
window_schedule_redraw(dnd->window);
}
static void
dnd_offer_destroy(struct dnd_offer *dnd_offer)
{
dnd_offer->refcount--;
if (dnd_offer->refcount == 0) {
wl_array_release(&dnd_offer->types);
free(dnd_offer);
}
}
static int
dnd_add_item(struct dnd *dnd, struct item *item)
{
int i;
for (i = 0; i < ARRAY_LENGTH(dnd->items); i++) {
if (dnd->items[i] == 0) {
dnd->items[i] = item;
return i;
}
}
return -1;
}
static struct item *
dnd_get_item(struct dnd *dnd, int32_t x, int32_t y)
{
@ -241,6 +284,7 @@ drag_target(void *data,
fprintf(stderr, "target %s\n", mime_type);
device = input_get_input_device(dnd_drag->input);
dnd_drag->mime_type = mime_type;
if (mime_type)
surface = dnd_drag->opaque;
else
@ -255,17 +299,35 @@ static void
drag_finish(void *data, struct wl_drag *drag, int fd)
{
struct dnd_drag *dnd_drag = data;
char text[] = "[drop data]";
fprintf(stderr, "got 'finish', fd %d, sending message\n", fd);
if (!dnd_drag->mime_type) {
dnd_add_item(dnd_drag->dnd, dnd_drag->item);
window_schedule_redraw(dnd_drag->dnd->window);
return;
}
struct dnd_flower_message dnd_flower_message;
dnd_flower_message.seed = dnd_drag->item->seed;
dnd_flower_message.x_offset = dnd_drag->x_offset;
dnd_flower_message.y_offset = dnd_drag->y_offset;
write(fd, text, sizeof text);
fprintf(stderr, "got 'finish', fd %d, sending dnd_flower_message\n", fd);
write(fd, &dnd_flower_message, sizeof dnd_flower_message);
close(fd);
/* The 'finish' event marks the end of the session on the drag
* source side and we need to clean up the drag object created
* and the local state. */
wl_drag_destroy(drag);
/* Destroy the item that has been dragged out */
cairo_surface_destroy(dnd_drag->item->surface);
free(dnd_drag->item);
cairo_surface_destroy(dnd_drag->translucent);
cairo_surface_destroy(dnd_drag->opaque);
free(dnd_drag);
@ -274,7 +336,10 @@ drag_finish(void *data, struct wl_drag *drag, int fd)
static void
drag_reject(void *data, struct wl_drag *drag)
{
fprintf(stderr, "drop rejected\n");
struct dnd_drag *dnd_drag = data;
dnd_add_item(dnd_drag->dnd, dnd_drag->item);
window_schedule_redraw(dnd_drag->dnd->window);
}
static const struct wl_drag_listener drag_listener = {
@ -312,9 +377,8 @@ drag_offer_pointer_focus(void *data,
* allocated. */
if (!surface) {
fprintf(stderr, "pointer focus NULL, session over\n");
wl_array_release(&dnd_offer->types);
free(dnd_offer);
wl_drag_offer_destroy(offer);
dnd_offer_destroy(dnd_offer);
return;
}
@ -328,8 +392,10 @@ drag_offer_pointer_focus(void *data,
dnd_offer->dnd = window_get_user_data(window);
if (!dnd_get_item(dnd_offer->dnd, surface_x, surface_y)) {
wl_drag_offer_accept(offer, time, "text/plain");
dnd_offer->drag_type = "text/plain";
wl_drag_offer_accept(offer, time, "application/x-wayland-dnd-flower");
dnd_offer->drag_type = "application/x-wayland-dnd-flower";
dnd_offer->x = surface_x;
dnd_offer->y = surface_y;
} else {
wl_drag_offer_accept(offer, time, NULL);
dnd_offer->drag_type = NULL;
@ -342,13 +408,14 @@ drag_offer_motion(void *data,
int32_t x, int32_t y, int32_t surface_x, int32_t surface_y)
{
struct dnd_offer *dnd_offer = data;
struct dnd *dnd = dnd_offer->dnd;
if (!dnd_get_item(dnd, surface_x, surface_y)) {
if (!dnd_get_item(dnd_offer->dnd, surface_x, surface_y)) {
fprintf(stderr, "drag offer motion %d, %d, accepting\n",
surface_x, surface_y);
wl_drag_offer_accept(offer, time, "text/plain");
dnd_offer->drag_type = "text/plain";
wl_drag_offer_accept(offer, time, "application/x-wayland-dnd-flower");
dnd_offer->drag_type = "application/x-wayland-dnd-flower";
dnd_offer->x = surface_x;
dnd_offer->y = surface_y;
} else {
fprintf(stderr, "drag offer motion %d, %d, declining\n",
surface_x, surface_y);
@ -361,19 +428,31 @@ static gboolean
drop_io_func(GIOChannel *source, GIOCondition condition, gpointer data)
{
struct dnd_offer *dnd_offer = data;
char buffer[256];
struct dnd *dnd = dnd_offer->dnd;
struct dnd_flower_message dnd_flower_message;
int fd;
unsigned int len;
GError *err = NULL;
struct item *item;
g_io_channel_read_chars(source, buffer, sizeof buffer, &len, &err);
fprintf(stderr, "read %d bytes: %s\n", len, buffer);
fd = g_io_channel_unix_get_fd(source);
len = read(fd, &dnd_flower_message, sizeof dnd_flower_message);
fprintf(stderr, "read %d bytes\n", len);
close(fd);
g_source_remove(dnd_offer->tag);
g_io_channel_unref(source);
item = item_create(dnd->display,
dnd_offer->x - dnd_flower_message.x_offset - 26,
dnd_offer->y - dnd_flower_message.y_offset - 66,
dnd_flower_message.seed);
dnd_add_item(dnd, item);
window_schedule_redraw(dnd->window);
dnd_offer_destroy(dnd_offer);
return TRUE;
}
@ -392,6 +471,7 @@ drag_offer_drop(void *data, struct wl_drag_offer *offer)
fprintf(stderr, "got 'drop', sending write end of pipe\n");
dnd_offer->refcount++;
pipe(p);
wl_drag_offer_receive(offer, p[1]);
close(p[1]);
@ -416,6 +496,8 @@ drag_offer_handler(struct wl_drag_offer *offer, struct display *display)
dnd_offer = malloc(sizeof *dnd_offer);
if (dnd_offer == NULL)
return;
dnd_offer->refcount = 1;
wl_drag_offer_add_listener(offer, &drag_offer_listener, dnd_offer);
wl_array_init(&dnd_offer->types);
@ -482,6 +564,7 @@ dnd_button_handler(struct window *window,
struct rectangle rectangle;
struct dnd_drag *dnd_drag;
struct wl_drag *drag;
int i;
window_get_child_rectangle(dnd->window, &rectangle);
input_get_position(input, &x, &y);
@ -496,6 +579,16 @@ dnd_button_handler(struct window *window,
dnd_drag->dnd = dnd;
dnd_drag->input = input;
dnd_drag->time = time;
dnd_drag->item = item;
dnd_drag->x_offset = x - item->x;
dnd_drag->y_offset = y - item->y;
for (i = 0; i < ARRAY_LENGTH(dnd->items); i++) {
if (item == dnd->items[i]){
dnd->items[i] = 0;
break;
}
}
dnd_drag->opaque =
create_drag_cursor(dnd_drag, item, x, y, 1);
@ -503,10 +596,10 @@ dnd_button_handler(struct window *window,
create_drag_cursor(dnd_drag, item, x, y, 0.2);
drag = window_create_drag(window);
wl_drag_offer(drag, "text/plain");
wl_drag_offer(drag, "text/html");
wl_drag_offer(drag, "application/x-wayland-dnd-flower");
window_activate_drag(drag, window, input, time);
wl_drag_add_listener(drag, &drag_listener, dnd_drag);
window_schedule_redraw(dnd->window);
}
}
@ -550,7 +643,7 @@ dnd_create(struct display *display)
x = (i % 4) * (item_width + item_padding) + item_padding;
y = (i / 4) * (item_height + item_padding) + item_padding;
if ((i ^ (i >> 2)) & 1)
dnd->items[i] = item_create(display, x, y);
dnd->items[i] = item_create(display, x, y, 0);
else
dnd->items[i] = NULL;
}
@ -583,10 +676,6 @@ main(int argc, char *argv[])
{
struct display *d;
struct dnd *dnd;
struct timeval tv;
gettimeofday(&tv, NULL);
srandom(tv.tv_usec);
d = display_create(&argc, &argv, option_entries);
if (d == NULL) {

Loading…
Cancel
Save