Skip to content

Commit

Permalink
data-control: Don't send offers to the clients that sent them
Browse files Browse the repository at this point in the history
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). Even if the client could read
its own selection, it is pointless to do so.

Here we fix the problem by not making offers back to the client that sent them.
The protocol has been updated to reflect this change.
Closes swaywm#2406.
  • Loading branch information
soreau committed Sep 21, 2020
1 parent 87836dc commit 9a0dca4
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 1 deletion.
3 changes: 2 additions & 1 deletion protocol/wlr-data-control-unstable-v1.xml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@
the primary clipboard selections). Immediately following the
wlr_data_control_device.data_offer event, the new data_offer object
will send out wlr_data_control_offer.offer events to describe the MIME
types it offers.
types it offers. Offers will be propagated to other clients but will
not be sent back to the client that made the offer.
</description>
<arg name="id" type="new_id" interface="zwlr_data_control_offer_v1"/>
</event>
Expand Down
22 changes: 22 additions & 0 deletions types/wlr_data_control_v1.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 9a0dca4

Please sign in to comment.