wayland: Don't send nil selections when changing clipboard data

Sending a nil selection followed by immediately destroying the selection offer is redundant, and avoiding intermediate nil offers helps some clipboard managers avoid potential race conditions.
This commit is contained in:
Frank Praznik
2026-07-27 11:54:10 -04:00
parent db673016fd
commit dfcbd16b4c
4 changed files with 13 additions and 36 deletions

View File

@@ -53,7 +53,9 @@ bool Wayland_SetClipboardData(SDL_VideoDevice *_this)
Wayland_DataSourceDestroy(source);
}
} else {
result = Wayland_DataDeviceClearSelection(data_device);
Wayland_DataSourceDestroy(data_device->selection_source);
data_device->selection_source = NULL;
result = true;
}
}
@@ -133,7 +135,9 @@ bool Wayland_SetPrimarySelectionText(SDL_VideoDevice *_this, const char *text)
Wayland_PrimarySelectionSourceDestroy(source);
}
} else {
result = Wayland_PrimarySelectionDeviceClearSelection(primary_selection_device);
Wayland_PrimarySelectionSourceDestroy(seat->primary_selection_device->selection_source);
seat->primary_selection_device->selection_source = NULL;
result = true;
}
} else {
result = SDL_SetError("Primary selection not supported");

View File

@@ -620,35 +620,6 @@ void Wayland_PrimarySelectionOfferDestroy(SDL_WaylandPrimarySelectionOffer *offe
}
}
bool Wayland_DataDeviceClearSelection(SDL_WaylandDataDevice *data_device)
{
if (!data_device || !data_device->data_device) {
return SDL_SetError("Invalid Data Device");
}
if (data_device->selection_source) {
wl_data_device_set_selection(data_device->data_device, NULL, data_device->seat->last_implicit_grab_serial);
Wayland_DataSourceDestroy(data_device->selection_source);
data_device->selection_source = NULL;
}
return true;
}
bool Wayland_PrimarySelectionDeviceClearSelection(SDL_WaylandPrimarySelectionDevice *primary_selection_device)
{
if (!primary_selection_device || !primary_selection_device->primary_selection_device) {
return SDL_SetError("Invalid Primary Selection Device");
}
if (primary_selection_device->selection_source) {
zwp_primary_selection_device_v1_set_selection(primary_selection_device->primary_selection_device,
NULL, primary_selection_device->seat->last_implicit_grab_serial);
Wayland_PrimarySelectionSourceDestroy(primary_selection_device->selection_source);
primary_selection_device->selection_source = NULL;
}
return true;
}
bool Wayland_DataDeviceSetSelection(SDL_WaylandDataDevice *data_device, SDL_WaylandDataSource *source, const char **mime_types, size_t mime_count)
{
if (!data_device) {
@@ -678,7 +649,8 @@ bool Wayland_DataDeviceSetSelection(SDL_WaylandDataDevice *data_device, SDL_Wayl
source->data_device = data_device;
} else {
Wayland_DataDeviceClearSelection(data_device);
Wayland_DataSourceDestroy(data_device->selection_source);
data_device->selection_source = NULL;
return SDL_SetError("No mime data");
}
@@ -714,7 +686,8 @@ bool Wayland_PrimarySelectionDeviceSetSelection(SDL_WaylandPrimarySelectionDevic
primary_selection_device->selection_source = source;
source->primary_selection_device = primary_selection_device;
} else {
Wayland_PrimarySelectionDeviceClearSelection(primary_selection_device);
Wayland_PrimarySelectionSourceDestroy(primary_selection_device->selection_source);
primary_selection_device->selection_source = NULL;
return SDL_SetError("No mime data");
}

View File

@@ -139,8 +139,6 @@ extern void Wayland_DataOfferDestroy(SDL_WaylandDataOffer *offer);
extern void Wayland_PrimarySelectionOfferDestroy(SDL_WaylandPrimarySelectionOffer *offer);
// Clipboard / Primary Selection
extern bool Wayland_DataDeviceClearSelection(SDL_WaylandDataDevice *device);
extern bool Wayland_PrimarySelectionDeviceClearSelection(SDL_WaylandPrimarySelectionDevice *device);
extern bool Wayland_DataDeviceSetSelection(SDL_WaylandDataDevice *device, SDL_WaylandDataSource *source, const char **mime_types, size_t mime_count);
extern bool Wayland_PrimarySelectionDeviceSetSelection(SDL_WaylandPrimarySelectionDevice *device, SDL_WaylandPrimarySelectionSource *source, const char *const *mime_types, size_t mime_count);
extern void Wayland_DataDeviceSetSerial(SDL_WaylandDataDevice *device, uint32_t serial);

View File

@@ -3698,10 +3698,12 @@ void Wayland_SeatDestroy(SDL_WaylandSeat *seat, bool shutting_down)
SDL_free(seat->name);
if (seat->data_device) {
Wayland_DataDeviceClearSelection(seat->data_device);
if (seat->data_device->selection_offer) {
Wayland_DataOfferDestroy(seat->data_device->selection_offer);
}
if (seat->data_device->selection_source) {
Wayland_DataSourceDestroy(seat->data_device->selection_source);
}
if (seat->data_device->drag_offer) {
Wayland_DataOfferDestroy(seat->data_device->drag_offer);
}