aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/types/wlr_data_device.h3
-rw-r--r--include/wlr/types/wlr_data_device.h13
-rw-r--r--types/data_device/wlr_data_device.c33
-rw-r--r--types/data_device/wlr_data_offer.c120
-rw-r--r--types/data_device/wlr_data_source.c35
-rw-r--r--types/data_device/wlr_drag.c46
6 files changed, 109 insertions, 141 deletions
diff --git a/include/types/wlr_data_device.h b/include/types/wlr_data_device.h
index 388e91a5..376c5f09 100644
--- a/include/types/wlr_data_device.h
+++ b/include/types/wlr_data_device.h
@@ -19,6 +19,7 @@ extern const struct wlr_surface_role drag_icon_surface_role;
struct wlr_data_offer *data_offer_create(struct wl_client *client,
struct wlr_data_source *source, uint32_t version);
void data_offer_update_action(struct wlr_data_offer *offer);
+void data_offer_destroy(struct wlr_data_offer *offer);
struct wlr_client_data_source *client_data_source_create(
struct wl_client *client, uint32_t version, uint32_t id,
@@ -26,7 +27,7 @@ struct wlr_client_data_source *client_data_source_create(
struct wlr_client_data_source *client_data_source_from_resource(
struct wl_resource *resource);
struct wlr_data_offer *data_source_send_offer(struct wlr_data_source *source,
- struct wlr_seat_client *target);
+ struct wl_resource *device_resource);
void data_source_notify_finish(struct wlr_data_source *source);
bool seat_client_start_drag(struct wlr_seat_client *client,
diff --git a/include/wlr/types/wlr_data_device.h b/include/wlr/types/wlr_data_device.h
index 9ce8f400..9c4ce995 100644
--- a/include/wlr/types/wlr_data_device.h
+++ b/include/wlr/types/wlr_data_device.h
@@ -12,14 +12,14 @@
#include <wayland-server.h>
#include <wlr/types/wlr_seat.h>
-extern const struct
-wlr_pointer_grab_interface wlr_data_device_pointer_drag_interface;
+extern const struct wlr_pointer_grab_interface
+ wlr_data_device_pointer_drag_interface;
-extern const struct
-wlr_keyboard_grab_interface wlr_data_device_keyboard_drag_interface;
+extern const struct wlr_keyboard_grab_interface
+ wlr_data_device_keyboard_drag_interface;
-extern const struct
-wlr_touch_grab_interface wlr_data_device_touch_drag_interface;
+extern const struct wlr_touch_grab_interface
+ wlr_data_device_touch_drag_interface;
struct wlr_data_device_manager {
struct wl_global *global;
@@ -72,7 +72,6 @@ struct wlr_data_source {
// source status
bool accepted;
- struct wlr_data_offer *offer;
// drag'n'drop status
enum wl_data_device_manager_dnd_action current_dnd_action;
diff --git a/types/data_device/wlr_data_device.c b/types/data_device/wlr_data_device.c
index a50f0b4a..f868ea37 100644
--- a/types/data_device/wlr_data_device.c
+++ b/types/data_device/wlr_data_device.c
@@ -94,25 +94,24 @@ static void data_device_handle_resource_destroy(struct wl_resource *resource) {
void wlr_seat_client_send_selection(struct wlr_seat_client *seat_client) {
- if (wl_list_empty(&seat_client->data_devices)) {
- return;
+ struct wlr_data_source *source = seat_client->seat->selection_source;
+ if (source != NULL) {
+ source->accepted = false;
}
- if (seat_client->seat->selection_source) {
- struct wlr_data_offer *offer = data_source_send_offer(
- seat_client->seat->selection_source, seat_client);
- if (offer == NULL) {
- return;
- }
-
- struct wl_resource *resource;
- wl_resource_for_each(resource, &seat_client->data_devices) {
- wl_data_device_send_selection(resource, offer->resource);
- }
- } else {
- struct wl_resource *resource;
- wl_resource_for_each(resource, &seat_client->data_devices) {
- wl_data_device_send_selection(resource, NULL);
+ struct wl_resource *device_resource;
+ wl_resource_for_each(device_resource, &seat_client->data_devices) {
+ if (source != NULL) {
+ struct wlr_data_offer *offer =
+ data_source_send_offer(source, device_resource);
+ if (offer == NULL) {
+ wl_client_post_no_memory(seat_client->client);
+ return;
+ }
+
+ wl_data_device_send_selection(device_resource, offer->resource);
+ } else {
+ wl_data_device_send_selection(device_resource, NULL);
}
}
}
diff --git a/types/data_device/wlr_data_offer.c b/types/data_device/wlr_data_offer.c
index 9847e07c..b8cec091 100644
--- a/types/data_device/wlr_data_offer.c
+++ b/types/data_device/wlr_data_offer.c
@@ -55,15 +55,10 @@ static uint32_t data_offer_choose_action(struct wlr_data_offer *offer) {
}
void data_offer_update_action(struct wlr_data_offer *offer) {
- if (!offer->source) {
- return;
- }
-
uint32_t action = data_offer_choose_action(offer);
if (offer->source->current_dnd_action == action) {
return;
}
-
offer->source->current_dnd_action = action;
if (offer->in_ask) {
@@ -78,50 +73,77 @@ void data_offer_update_action(struct wlr_data_offer *offer) {
}
}
-static void data_offer_accept(struct wl_client *client,
+static void data_offer_handle_accept(struct wl_client *client,
struct wl_resource *resource, uint32_t serial, const char *mime_type) {
struct wlr_data_offer *offer = data_offer_from_resource(resource);
-
- if (!offer->source || offer != offer->source->offer) {
+ if (offer == NULL) {
return;
}
- // TODO check that client is currently focused by the input device
-
wlr_data_source_accept(offer->source, serial, mime_type);
}
-static void data_offer_receive(struct wl_client *client,
+static void data_offer_handle_receive(struct wl_client *client,
struct wl_resource *resource, const char *mime_type, int32_t fd) {
struct wlr_data_offer *offer = data_offer_from_resource(resource);
-
- if (offer->source && offer == offer->source->offer) {
- wlr_data_source_send(offer->source, mime_type, fd);
- } else {
+ if (offer == NULL) {
close(fd);
+ return;
}
+
+ wlr_data_source_send(offer->source, mime_type, fd);
}
-static void data_offer_destroy(struct wl_client *client,
+static void data_offer_dnd_finish(struct wlr_data_offer *offer) {
+ struct wlr_data_source *source = offer->source;
+ if (source->actions < 0) {
+ return;
+ }
+
+ if (offer->in_ask) {
+ wlr_data_source_dnd_action(source, source->current_dnd_action);
+ }
+
+ wlr_data_source_dnd_finish(source);
+}
+
+static void data_offer_handle_destroy(struct wl_client *client,
struct wl_resource *resource) {
+ struct wlr_data_offer *offer = data_offer_from_resource(resource);
+ if (offer == NULL) {
+ goto out;
+ }
+
+ // If the drag destination has version < 3, wl_data_offer.finish
+ // won't be called, so do this here as a safety net, because
+ // we still want the version >= 3 drag source to be happy.
+ if (wl_resource_get_version(offer->resource) <
+ WL_DATA_OFFER_ACTION_SINCE_VERSION) {
+ data_offer_dnd_finish(offer);
+ }
+
+out:
wl_resource_destroy(resource);
}
-static void data_offer_finish(struct wl_client *client,
+static void data_offer_handle_finish(struct wl_client *client,
struct wl_resource *resource) {
struct wlr_data_offer *offer = data_offer_from_resource(resource);
-
- if (!offer->source || offer->source->offer != offer) {
+ if (offer == NULL) {
return;
}
- data_source_notify_finish(offer->source);
+ data_offer_dnd_finish(offer);
+ data_offer_destroy(offer);
}
-static void data_offer_set_actions(struct wl_client *client,
+static void data_offer_handle_set_actions(struct wl_client *client,
struct wl_resource *resource, uint32_t actions,
uint32_t preferred_action) {
struct wlr_data_offer *offer = data_offer_from_resource(resource);
+ if (offer == NULL) {
+ return;
+ }
if (actions & ~DATA_DEVICE_ALL_ACTIONS) {
wl_resource_post_error(offer->resource,
@@ -144,52 +166,36 @@ static void data_offer_set_actions(struct wl_client *client,
data_offer_update_action(offer);
}
-static void data_offer_handle_resource_destroy(struct wl_resource *resource) {
- struct wlr_data_offer *offer = data_offer_from_resource(resource);
-
- if (!offer->source) {
- goto out;
+void data_offer_destroy(struct wlr_data_offer *offer) {
+ if (offer == NULL) {
+ return;
}
wl_list_remove(&offer->source_destroy.link);
- if (offer->source->offer != offer) {
- goto out;
- }
-
- // If the drag destination has version < 3, wl_data_offer.finish
- // won't be called, so do this here as a safety net, because
- // we still want the version >= 3 drag source to be happy.
- if (wl_resource_get_version(offer->resource) <
- WL_DATA_OFFER_ACTION_SINCE_VERSION) {
- data_source_notify_finish(offer->source);
- offer->source->offer = NULL;
- } else if (offer->source->impl->dnd_finish) {
- // source->cancel can free the source
- offer->source->offer = NULL;
- wlr_data_source_cancel(offer->source);
- } else {
- offer->source->offer = NULL;
- }
-
-out:
+ // Make the resource inert
+ wl_resource_set_user_data(offer->resource, NULL);
free(offer);
}
static const struct wl_data_offer_interface data_offer_impl = {
- .accept = data_offer_accept,
- .receive = data_offer_receive,
- .destroy = data_offer_destroy,
- .finish = data_offer_finish,
- .set_actions = data_offer_set_actions,
+ .accept = data_offer_handle_accept,
+ .receive = data_offer_handle_receive,
+ .destroy = data_offer_handle_destroy,
+ .finish = data_offer_handle_finish,
+ .set_actions = data_offer_handle_set_actions,
};
-static void handle_offer_source_destroyed(struct wl_listener *listener,
+static void data_offer_handle_resource_destroy(struct wl_resource *resource) {
+ struct wlr_data_offer *offer = data_offer_from_resource(resource);
+ data_offer_destroy(offer);
+}
+
+static void data_offer_handle_source_destroy(struct wl_listener *listener,
void *data) {
struct wlr_data_offer *offer =
wl_container_of(listener, offer, source_destroy);
-
- offer->source = NULL;
+ data_offer_destroy(offer);
}
struct wlr_data_offer *data_offer_create(struct wl_client *client,
@@ -200,8 +206,8 @@ struct wlr_data_offer *data_offer_create(struct wl_client *client,
}
offer->source = source;
- offer->resource = wl_resource_create(client,
- &wl_data_offer_interface, version, 0);
+ offer->resource =
+ wl_resource_create(client, &wl_data_offer_interface, version, 0);
if (offer->resource == NULL) {
free(offer);
return NULL;
@@ -209,7 +215,7 @@ struct wlr_data_offer *data_offer_create(struct wl_client *client,
wl_resource_set_implementation(offer->resource, &data_offer_impl, offer,
data_offer_handle_resource_destroy);
- offer->source_destroy.notify = handle_offer_source_destroyed;
+ offer->source_destroy.notify = data_offer_handle_source_destroy;
wl_signal_add(&source->events.destroy, &offer->source_destroy);
return offer;
diff --git a/types/data_device/wlr_data_source.c b/types/data_device/wlr_data_source.c
index 64db3a70..413f461a 100644
--- a/types/data_device/wlr_data_source.c
+++ b/types/data_device/wlr_data_source.c
@@ -11,47 +11,22 @@
#include "types/wlr_data_device.h"
#include "util/signal.h"
-void data_source_notify_finish(struct wlr_data_source *source) {
- assert(source->offer);
- if (source->actions < 0) {
- return;
- }
-
- if (source->offer->in_ask) {
- wlr_data_source_dnd_action(source, source->current_dnd_action);
- }
-
- source->offer = NULL;
- wlr_data_source_dnd_finish(source);
-}
-
struct wlr_data_offer *data_source_send_offer(struct wlr_data_source *source,
- struct wlr_seat_client *target) {
- if (wl_list_empty(&target->data_devices)) {
- return NULL;
- }
-
- uint32_t version = wl_resource_get_version(
- wl_resource_from_link(target->data_devices.next));
-
- struct wlr_data_offer *offer =
- data_offer_create(target->client, source, version);
+ struct wl_resource *device_resource) {
+ struct wl_client *client = wl_resource_get_client(device_resource);
+ uint32_t version = wl_resource_get_version(device_resource);
+ struct wlr_data_offer *offer = data_offer_create(client, source, version);
if (offer == NULL) {
return NULL;
}
- struct wl_resource *target_resource;
- wl_resource_for_each(target_resource, &target->data_devices) {
- wl_data_device_send_data_offer(target_resource, offer->resource);
- }
+ wl_data_device_send_data_offer(device_resource, offer->resource);
char **p;
wl_array_for_each(p, &source->mime_types) {
wl_data_offer_send_offer(offer->resource, *p);
}
- source->offer = offer;
- source->accepted = false;
return offer;
}
diff --git a/types/data_device/wlr_drag.c b/types/data_device/wlr_drag.c
index 8ed6e034..8e737597 100644
--- a/types/data_device/wlr_drag.c
+++ b/types/data_device/wlr_drag.c
@@ -47,25 +47,27 @@ static void drag_set_focus(struct wlr_drag *drag,
return;
}
- if (drag->source && drag->source->offer) {
- // unlink the offer from the source
- wl_list_remove(&drag->source->offer->source_destroy.link);
- drag->source->offer->source = NULL;
- drag->source->offer = NULL;
- }
-
struct wlr_seat_client *focus_client = wlr_seat_client_for_wl_client(
drag->seat_client->seat, wl_resource_get_client(surface->resource));
if (!focus_client) {
return;
}
- struct wl_resource *offer_resource = NULL;
- if (drag->source) {
+ if (drag->source != NULL) {
drag->source->accepted = false;
- struct wlr_data_offer *offer = data_source_send_offer(drag->source,
- focus_client);
- if (offer != NULL) {
+
+ uint32_t serial =
+ wl_display_next_serial(drag->seat_client->seat->display);
+
+ struct wl_resource *device_resource;
+ wl_resource_for_each(device_resource, &focus_client->data_devices) {
+ struct wlr_data_offer *offer =
+ data_source_send_offer(drag->source, device_resource);
+ if (offer == NULL) {
+ wl_resource_post_no_memory(device_resource);
+ return;
+ }
+
data_offer_update_action(offer);
if (wl_resource_get_version(offer->resource) >=
@@ -74,18 +76,10 @@ static void drag_set_focus(struct wlr_drag *drag,
drag->source->actions);
}
- offer_resource = offer->resource;
- }
- }
-
- if (!wl_list_empty(&focus_client->data_devices)) {
- uint32_t serial =
- wl_display_next_serial(drag->seat_client->seat->display);
- struct wl_resource *resource;
- wl_resource_for_each(resource, &focus_client->data_devices) {
- wl_data_device_send_enter(resource, serial, surface->resource,
+ wl_data_device_send_enter(device_resource, serial,
+ surface->resource,
wl_fixed_from_double(sx), wl_fixed_from_double(sy),
- offer_resource);
+ offer->resource);
}
}
@@ -174,12 +168,6 @@ static uint32_t drag_handle_pointer_button(struct wlr_seat_pointer_grab *grab,
}
wlr_data_source_dnd_drop(drag->source);
- if (drag->source->offer != NULL) {
- drag->source->offer->in_ask =
- drag->source->current_dnd_action ==
- WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
- }
-
struct wlr_drag_drop_event event = {
.drag = drag,
.time = time,