data_offer_destroy(struct ds_data_offer *offer)
{
wl_list_remove(&offer->link);
- wl_list_remove(&offer->source_destroy.link);
+
+ if (offer->source) {
+ wl_list_remove(&offer->source_destroy.link);
+
+ // 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 (offer->type == DS_DATA_OFFER_DRAG) {
+ if (wl_resource_get_version(offer->resource) <
+ WL_DATA_OFFER_ACTION_SINCE_VERSION) {
+ data_offer_source_dnd_finish(offer);
+ }
+ else if (offer->source->iface->dnd_finish) {
+ ds_data_source_destroy(offer->source);
+ }
+ }
+ }
wl_resource_set_user_data(offer->resource, NULL);