From dfcbd16b4c7b1666eaa2e45b51a0ab9657ae3fed Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Mon, 27 Jul 2026 11:54:10 -0400 Subject: [PATCH] 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. --- src/video/wayland/SDL_waylandclipboard.c | 8 +++-- src/video/wayland/SDL_waylanddatamanager.c | 35 +++------------------- src/video/wayland/SDL_waylanddatamanager.h | 2 -- src/video/wayland/SDL_waylandevents.c | 4 ++- 4 files changed, 13 insertions(+), 36 deletions(-) diff --git a/src/video/wayland/SDL_waylandclipboard.c b/src/video/wayland/SDL_waylandclipboard.c index a8409bc6f6..81f8f8c3c5 100644 --- a/src/video/wayland/SDL_waylandclipboard.c +++ b/src/video/wayland/SDL_waylandclipboard.c @@ -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"); diff --git a/src/video/wayland/SDL_waylanddatamanager.c b/src/video/wayland/SDL_waylanddatamanager.c index 1a293247fb..5137c3bef1 100644 --- a/src/video/wayland/SDL_waylanddatamanager.c +++ b/src/video/wayland/SDL_waylanddatamanager.c @@ -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"); } diff --git a/src/video/wayland/SDL_waylanddatamanager.h b/src/video/wayland/SDL_waylanddatamanager.h index 382d046ac1..0a9d330a77 100644 --- a/src/video/wayland/SDL_waylanddatamanager.h +++ b/src/video/wayland/SDL_waylanddatamanager.h @@ -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); diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index e4de4351f9..14031d8e4c 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -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); }