From c13a9351ba6a705c54dd99ebc35bf8c2e7cfef94 Mon Sep 17 00:00:00 2001 From: Scott Moreau Date: Mon, 21 Sep 2020 03:53:24 -0600 Subject: [PATCH] data-control: Don't send offers to the clients that sent them If a client is listening for offers and sends an offer, it will block forever when it attempts to receive the offer and read from the file descriptor. This is because the offer is sent back to the client that sent it. Since the writing and reading ends are in the same client, it never has a chance to write, barring methods to work around this problem. Here we fix the problem by not making offers back to the client that sent them. Closes #2406. --- types/wlr_data_control_v1.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/types/wlr_data_control_v1.c b/types/wlr_data_control_v1.c index 239e238ad4..d57ea0222b 100644 --- a/types/wlr_data_control_v1.c +++ b/types/wlr_data_control_v1.c @@ -457,6 +457,17 @@ static void control_send_selection(struct wlr_data_control_device_v1 *device) { } device->selection_offer_resource = NULL; + + struct client_data_source *client_source = + wl_container_of(source, client_source, source); + if (client_source && device->resource) { + struct wl_resource *source_resource = client_source->resource; + // Don't send the offer back to the client that sent it + if (source_resource && wl_resource_get_client(source_resource) == + wl_resource_get_client(device->resource)) + return; + } + if (source != NULL) { device->selection_offer_resource = create_offer(device, &source->mime_types, false); @@ -488,6 +499,17 @@ static void control_send_primary_selection( } device->primary_selection_offer_resource = NULL; + + struct client_primary_selection_source *client_source = + wl_container_of(source, client_source, source); + if (client_source && device->resource) { + struct wl_resource *source_resource = client_source->resource; + // Don't send the offer back to the client that sent it + if (source_resource && wl_resource_get_client(source_resource) == + wl_resource_get_client(device->resource)) + return; + } + if (source != NULL) { device->primary_selection_offer_resource = create_offer(device, &source->mime_types, true);