From 8b86393d9806f26d48a8167d3ea37c9abfa073f6 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Tue, 21 Jul 2026 19:51:04 -0400 Subject: [PATCH] wayland: Don't clear the clipboard when a nil selection is ignored If the previous selection offering was recursive, a nil selection should be ignored, or clearing the clipboard may clear the backing memory of the client's selection offering as well. --- src/video/wayland/SDL_waylanddatamanager.c | 5 +++++ src/video/wayland/SDL_waylandevents.c | 12 +++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/video/wayland/SDL_waylanddatamanager.c b/src/video/wayland/SDL_waylanddatamanager.c index 4501efaa1a606..717611bfb4922 100644 --- a/src/video/wayland/SDL_waylanddatamanager.c +++ b/src/video/wayland/SDL_waylanddatamanager.c @@ -422,6 +422,11 @@ static void offer_source_done_handler(void *data, struct wl_callback *callback, SDL_free(id); if (source_is_external) { Wayland_data_offer_notify_from_mimes(offer, false); + } else { + // Recursive data offer; just destroy it. + SDL_WaylandDataDevice *data_device = offer->data_device; + Wayland_data_offer_destroy(offer); + data_device->selection_offer = NULL; } } } diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index 56e6b61b94171..8ef55cfabbbd7 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -3050,12 +3050,14 @@ static void data_device_handle_selection(void *data, struct wl_data_device *wl_d SDL_LogTrace(SDL_LOG_CATEGORY_INPUT, ". In data_device_listener . data_device_handle_selection on data_offer 0x%08x", (id ? WAYLAND_wl_proxy_get_id((struct wl_proxy *)id) : -1)); - if (data_device->selection_offer != offer) { - Wayland_data_offer_destroy(data_device->selection_offer); - data_device->selection_offer = offer; - } - Wayland_data_offer_notify_from_mimes(offer, true); + // Don't notify when clearing the old selection offer if doing so will inadvertently clear the selection source. + const bool notify = offer || (!offer && data_device->selection_offer && (!data_device->selection_offer->callback || !data_device->selection_source)); + Wayland_data_offer_destroy(data_device->selection_offer); + data_device->selection_offer = offer; + if (notify) { + Wayland_data_offer_notify_from_mimes(offer, true); + } } static const struct wl_data_device_listener data_device_listener = {