SDL: wayland: Add additional MIME types for text drag & drop

From c4be7f77a64675a9ed1d29387064a59f422375fc Mon Sep 17 00:00:00 2001
From: Frank Praznik <[EMAIL REDACTED]>
Date: Wed, 5 Mar 2025 20:14:19 -0500
Subject: [PATCH] wayland: Add additional MIME types for text drag & drop

Previously, it only specifically accepted "text/plain;charset=utf8", which caused it to reject valid text from certain apps.
---
 src/video/wayland/SDL_waylandclipboard.c   | 18 +++++++++++++++---
 src/video/wayland/SDL_waylanddatamanager.h |  1 +
 src/video/wayland/SDL_waylandevents.c      | 19 +++++++++++++------
 3 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/src/video/wayland/SDL_waylandclipboard.c b/src/video/wayland/SDL_waylandclipboard.c
index 62187332906cc..caab2e30b77e0 100644
--- a/src/video/wayland/SDL_waylandclipboard.c
+++ b/src/video/wayland/SDL_waylandclipboard.c
@@ -142,8 +142,13 @@ char *Wayland_GetPrimarySelectionText(SDL_VideoDevice *_this)
         primary_selection_device = video_data->input->primary_selection_device;
         if (primary_selection_device->selection_source) {
             text = Wayland_primary_selection_source_get_data(primary_selection_device->selection_source, TEXT_MIME, &length);
-        } else if (Wayland_primary_selection_offer_has_mime(primary_selection_device->selection_offer, TEXT_MIME)) {
-            text = Wayland_primary_selection_offer_receive(primary_selection_device->selection_offer, TEXT_MIME, &length);
+        } else {
+            for (size_t i = 0; i < SDL_arraysize(text_mime_types); i++) {
+                if (Wayland_primary_selection_offer_has_mime(primary_selection_device->selection_offer, text_mime_types[i])) {
+                    text = Wayland_primary_selection_offer_receive(primary_selection_device->selection_offer, text_mime_types[i], &length);
+                    break;
+                }
+            }
         }
     }
 
@@ -165,7 +170,14 @@ bool Wayland_HasPrimarySelectionText(SDL_VideoDevice *_this)
         if (primary_selection_device->selection_source) {
             result = true;
         } else {
-            result = Wayland_primary_selection_offer_has_mime(primary_selection_device->selection_offer, TEXT_MIME);
+            size_t mime_count = 0;
+            const char **mime_types = Wayland_GetTextMimeTypes(_this, &mime_count);
+            for (size_t i = 0; i < mime_count; i++) {
+                if (Wayland_primary_selection_offer_has_mime(primary_selection_device->selection_offer, mime_types[i])) {
+                    result = true;
+                    break;
+                }
+            }
         }
     }
     return result;
diff --git a/src/video/wayland/SDL_waylanddatamanager.h b/src/video/wayland/SDL_waylanddatamanager.h
index adca17b285d66..fd55634c82014 100644
--- a/src/video/wayland/SDL_waylanddatamanager.h
+++ b/src/video/wayland/SDL_waylanddatamanager.h
@@ -85,6 +85,7 @@ typedef struct
     uint32_t drag_serial;
     SDL_WaylandDataOffer *drag_offer;
     SDL_WaylandDataOffer *selection_offer;
+    const char *mime_type;
     bool has_mime_file, has_mime_text;
     SDL_Window *dnd_window;
 
diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c
index 49864198544be..418dc449bd5de 100644
--- a/src/video/wayland/SDL_waylandevents.c
+++ b/src/video/wayland/SDL_waylandevents.c
@@ -34,6 +34,7 @@
 #include "SDL_waylandevents_c.h"
 #include "SDL_waylandwindow.h"
 #include "SDL_waylandmouse.h"
+#include "SDL_waylandclipboard.h"
 
 #include "pointer-constraints-unstable-v1-client-protocol.h"
 #include "relative-pointer-unstable-v1-client-protocol.h"
@@ -2258,17 +2259,25 @@ static void data_device_handle_enter(void *data, struct wl_data_device *wl_data_
 #ifdef SDL_USE_LIBDBUS
         if (Wayland_data_offer_has_mime(data_device->drag_offer, FILE_PORTAL_MIME)) {
             data_device->has_mime_file = true;
+            data_device->mime_type = FILE_PORTAL_MIME;
             wl_data_offer_accept(id, serial, FILE_PORTAL_MIME);
         }
 #endif
         if (Wayland_data_offer_has_mime(data_device->drag_offer, FILE_MIME)) {
             data_device->has_mime_file = true;
+            data_device->mime_type = FILE_MIME;
             wl_data_offer_accept(id, serial, FILE_MIME);
         }
 
-        if (Wayland_data_offer_has_mime(data_device->drag_offer, TEXT_MIME)) {
-            data_device->has_mime_text = true;
-            wl_data_offer_accept(id, serial, TEXT_MIME);
+        size_t mime_count = 0;
+        const char **text_mime_types = Wayland_GetTextMimeTypes(SDL_GetVideoDevice(), &mime_count);
+        for (size_t i = 0; i < mime_count; ++i) {
+            if (Wayland_data_offer_has_mime(data_device->drag_offer, text_mime_types[i])) {
+                data_device->has_mime_text = true;
+                data_device->mime_type = text_mime_types[i];
+                wl_data_offer_accept(id, serial, text_mime_types[i]);
+                break;
+            }
         }
 
         // SDL only supports "copy" style drag and drop
@@ -2411,9 +2420,7 @@ static void data_device_handle_drop(void *data, struct wl_data_device *wl_data_d
          * non paths that are not visible to the application
          */
         if (!drop_handled) {
-            const char *mime_type = data_device->has_mime_file ? FILE_MIME : (data_device->has_mime_text ? TEXT_MIME : "");
-            void *buffer = Wayland_data_offer_receive(data_device->drag_offer,
-                                                      mime_type, &length);
+            void *buffer = Wayland_data_offer_receive(data_device->drag_offer, data_device->mime_type, &length);
             if (data_device->has_mime_file) {
                 if (buffer) {
                     char *saveptr = NULL;