diff --git a/clients/dnd.c b/clients/dnd.c index de1ca473..c6f0f183 100644 --- a/clients/dnd.c +++ b/clients/dnd.c @@ -37,12 +37,16 @@ #include "window.h" #include "../shared/cairo-util.h" +struct dnd_drag; + struct dnd { struct window *window; struct widget *widget; struct display *display; uint32_t key; struct item *items[16]; + int self_only; + struct dnd_drag *current_drag; }; struct dnd_drag { @@ -366,6 +370,7 @@ dnd_button_handler(struct widget *widget, struct wl_buffer *buffer; unsigned int i; uint32_t serial; + cairo_surface_t *icon; widget_get_allocation(dnd->widget, &allocation); input_get_position(input, &x, &y); @@ -397,15 +402,20 @@ dnd_button_handler(struct widget *widget, input_ungrab(input); - dnd_drag->data_source = - display_create_data_source(dnd->display); - wl_data_source_add_listener(dnd_drag->data_source, - &data_source_listener, - dnd_drag); - wl_data_source_offer(dnd_drag->data_source, - "application/x-wayland-dnd-flower"); - wl_data_source_offer(dnd_drag->data_source, - "text/plain; charset=utf-8"); + if (dnd->self_only) { + dnd_drag->data_source = NULL; + } else { + dnd_drag->data_source = + display_create_data_source(dnd->display); + wl_data_source_add_listener(dnd_drag->data_source, + &data_source_listener, + dnd_drag); + wl_data_source_offer(dnd_drag->data_source, + "application/x-wayland-dnd-flower"); + wl_data_source_offer(dnd_drag->data_source, + "text/plain; charset=utf-8"); + } + wl_data_device_start_drag(input_get_data_device(input), dnd_drag->data_source, window_get_wl_surface(dnd->window), @@ -419,12 +429,18 @@ dnd_button_handler(struct widget *widget, dnd_drag->translucent = create_drag_cursor(dnd_drag, item, x, y, 0.2); - buffer = display_get_buffer_for_surface(dnd->display, dnd_drag->translucent); + if (dnd->self_only) + icon = dnd_drag->opaque; + else + icon = dnd_drag->translucent; + + buffer = display_get_buffer_for_surface(dnd->display, icon); wl_surface_attach(dnd_drag->drag_surface, buffer, -dnd_drag->hotspot_x, -dnd_drag->hotspot_y); wl_surface_damage(dnd_drag->drag_surface, 0, 0, dnd_drag->width, dnd_drag->height); + dnd->current_drag = dnd_drag; window_schedule_redraw(dnd->window); } } @@ -445,7 +461,11 @@ static int dnd_enter_handler(struct widget *widget, struct input *input, float x, float y, void *data) { - return lookup_cursor(data, x, y); + struct dnd *dnd = data; + + dnd->current_drag = NULL; + + return lookup_cursor(dnd, x, y); } static int @@ -463,10 +483,13 @@ dnd_data_handler(struct window *window, { struct dnd *dnd = data; - if (!dnd_get_item(dnd, x, y)) { - input_accept(input, types[0]); - } else { + if (!types) + return; + + if (dnd_get_item(dnd, x, y) || dnd->self_only) { input_accept(input, NULL); + } else { + input_accept(input, types[0]); } } @@ -501,15 +524,26 @@ dnd_drop_handler(struct window *window, struct input *input, int32_t x, int32_t y, void *data) { struct dnd *dnd = data; + struct dnd_flower_message message; if (dnd_get_item(dnd, x, y)) { fprintf(stderr, "got 'drop', but no target\n"); return; } - input_receive_drag_data(input, - "application/x-wayland-dnd-flower", - dnd_receive_func, dnd); + if (!dnd->self_only) { + input_receive_drag_data(input, + "application/x-wayland-dnd-flower", + dnd_receive_func, dnd); + } else if (dnd->current_drag) { + message.seed = dnd->current_drag->item->seed; + message.x_offset = dnd->current_drag->x_offset; + message.y_offset = dnd->current_drag->y_offset; + dnd_receive_func(&message, sizeof message, x, y, dnd); + dnd->current_drag = NULL; + } else { + fprintf(stderr, "ignoring drop from another client\n"); + } } static struct dnd * @@ -564,6 +598,8 @@ int main(int argc, char *argv[]) { struct display *d; + struct dnd *dnd; + int i; d = display_create(argc, argv); if (d == NULL) { @@ -571,7 +607,11 @@ main(int argc, char *argv[]) return -1; } - dnd_create(d); + dnd = dnd_create(d); + + for (i = 1; i < argc; i++) + if (strcmp("--self-only", argv[i]) == 0) + dnd->self_only = 1; display_run(d); diff --git a/clients/window.c b/clients/window.c index 0c6f5561..9eb62e6c 100644 --- a/clients/window.c +++ b/clients/window.c @@ -2099,22 +2099,30 @@ data_device_enter(void *data, struct wl_data_device *data_device, { struct input *input = data; struct window *window; + void *types_data; float x = wl_fixed_to_double(x_w); float y = wl_fixed_to_double(y_w); char **p; input->pointer_enter_serial = serial; - input->drag_offer = wl_data_offer_get_user_data(offer); window = wl_surface_get_user_data(surface); input->pointer_focus = window; - p = wl_array_add(&input->drag_offer->types, sizeof *p); - *p = NULL; + if (offer) { + input->drag_offer = wl_data_offer_get_user_data(offer); + + p = wl_array_add(&input->drag_offer->types, sizeof *p); + *p = NULL; + + types_data = input->drag_offer->types.data; + } else { + input->drag_offer = NULL; + types_data = NULL; + } window = input->pointer_focus; if (window->data_handler) - window->data_handler(window, input, x, y, - input->drag_offer->types.data, + window->data_handler(window, input, x, y, types_data, window->user_data); } @@ -2123,8 +2131,10 @@ data_device_leave(void *data, struct wl_data_device *data_device) { struct input *input = data; - data_offer_destroy(input->drag_offer); - input->drag_offer = NULL; + if (input->drag_offer) { + data_offer_destroy(input->drag_offer); + input->drag_offer = NULL; + } } static void @@ -2135,13 +2145,18 @@ data_device_motion(void *data, struct wl_data_device *data_device, struct window *window = input->pointer_focus; float x = wl_fixed_to_double(x_w); float y = wl_fixed_to_double(y_w); + void *types_data; input->sx = x; input->sy = y; + if (input->drag_offer) + types_data = input->drag_offer->types.data; + else + types_data = NULL; + if (window->data_handler) - window->data_handler(window, input, x, y, - input->drag_offer->types.data, + window->data_handler(window, input, x, y, types_data, window->user_data); }