Added SDL_DROPTEXT event, for dragging and dropping string data.
authorRyan C. Gordon <icculus@icculus.org>
Tue, 05 Jan 2016 02:26:45 -0500
changeset 10020 08b9e569e1ce
parent 10019 36f7e8084508
child 10021 3beca914a2ad
Added SDL_DROPTEXT event, for dragging and dropping string data. This patch is based on work in Unreal Engine 4's fork of SDL, compliments of Epic Games.
include/SDL_events.h
src/events/SDL_dropevents.c
src/events/SDL_dropevents_c.h
src/video/x11/SDL_x11events.c
test/testdropfile.c
--- a/include/SDL_events.h	Mon Jan 04 23:52:40 2016 -0500
+++ b/include/SDL_events.h	Tue Jan 05 02:26:45 2016 -0500
@@ -136,6 +136,7 @@
 
     /* Drag and drop events */
     SDL_DROPFILE        = 0x1000, /**< The system requests a file open */
+    SDL_DROPTEXT,                 /**< text/plain drag-and-drop event */
 
     /* Audio hotplug events */
     SDL_AUDIODEVICEADDED = 0x1100, /**< A new audio device is available */
--- a/src/events/SDL_dropevents.c	Mon Jan 04 23:52:40 2016 -0500
+++ b/src/events/SDL_dropevents.c	Tue Jan 05 02:26:45 2016 -0500
@@ -27,20 +27,33 @@
 #include "SDL_dropevents_c.h"
 
 
-int
-SDL_SendDropFile(const char *file)
+static int
+SDL_SendDrop(const SDL_EventType evtype, const char *data)
 {
     int posted;
 
     /* Post the event, if desired */
     posted = 0;
-    if (SDL_GetEventState(SDL_DROPFILE) == SDL_ENABLE) {
+    if (SDL_GetEventState(evtype) == SDL_ENABLE) {
         SDL_Event event;
-        event.type = SDL_DROPFILE;
-        event.drop.file = SDL_strdup(file);
+        SDL_zero(event);
+        event.type = evtype;
+        event.drop.file = SDL_strdup(data);
         posted = (SDL_PushEvent(&event) > 0);
     }
-    return (posted);
+    return posted;
+}
+
+int
+SDL_SendDropFile(const char *file)
+{
+    return SDL_SendDrop(SDL_DROPFILE, file);
+}
+
+int
+SDL_SendDropText(const char *text)
+{
+    return SDL_SendDrop(SDL_DROPTEXT, text);
 }
 
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/events/SDL_dropevents_c.h	Mon Jan 04 23:52:40 2016 -0500
+++ b/src/events/SDL_dropevents_c.h	Tue Jan 05 02:26:45 2016 -0500
@@ -24,6 +24,7 @@
 #define _SDL_dropevents_c_h
 
 extern int SDL_SendDropFile(const char *file);
+extern int SDL_SendDropText(const char *text);
 
 #endif /* _SDL_dropevents_c_h */
 
--- a/src/video/x11/SDL_x11events.c	Mon Jan 04 23:52:40 2016 -0500
+++ b/src/video/x11/SDL_x11events.c	Tue Jan 05 02:26:45 2016 -0500
@@ -117,7 +117,9 @@
     int i;
     for (i=0; i < list_count && request == None; i++) {
         name = X11_XGetAtomName(disp, list[i]);
-        if (strcmp("text/uri-list", name)==0) request = list[i];
+        if ((SDL_strcmp("text/uri-list", name) == 0) || (SDL_strcmp("text/plain", name) == 0)) {
+             request = list[i];
+        }
         X11_XFree(name);
     }
     return request;
@@ -1223,37 +1225,19 @@
                 X11_ReadProperty(&p, display, data->xwindow, videodata->PRIMARY);
 
                 if (p.format == 8) {
-                    SDL_bool expect_lf = SDL_FALSE;
-                    char *start = NULL;
-                    char *scan = (char*)p.data;
-                    char *fn;
-                    char *uri;
-                    int length = 0;
-                    while (p.count--) {
-                        if (!expect_lf) {
-                            if (*scan == 0x0D) {
-                                expect_lf = SDL_TRUE;
-                            }
-                            if (start == NULL) {
-                                start = scan;
-                                length = 0;
+                    /* !!! FIXME: don't use strtok here. It's not reentrant and not in SDL_stdinc. */
+                    char* name = X11_XGetAtomName(display, target);
+                    char *token = strtok((char *) p.data, "\r\n");
+                    while (token != NULL) {
+                        if (SDL_strcmp("text/plain", name)==0) {
+                            SDL_SendDropText(token);
+                        } else if (SDL_strcmp("text/uri-list", name)==0) {
+                            char *fn = X11_URIToLocal(token);
+                            if (fn) {
+                                SDL_SendDropFile(fn);
                             }
-                            length++;
-                        } else {
-                            if (*scan == 0x0A && length > 0) {
-                                uri = SDL_malloc(length--);
-                                SDL_memcpy(uri, start, length);
-                                uri[length] = '\0';
-                                fn = X11_URIToLocal(uri);
-                                if (fn) {
-                                    SDL_SendDropFile(fn);
-                                }
-                                SDL_free(uri);
-                            }
-                            expect_lf = SDL_FALSE;
-                            start = NULL;
                         }
-                        scan++;
+                        token = strtok(NULL, "\r\n");
                     }
                 }
 
--- a/test/testdropfile.c	Mon Jan 04 23:52:40 2016 -0500
+++ b/test/testdropfile.c	Tue Jan 05 02:26:45 2016 -0500
@@ -77,9 +77,10 @@
         while (SDL_PollEvent(&event)) {
             SDLTest_CommonEvent(state, &event, &done);
 
-            if (event.type == SDL_DROPFILE) {
+            if ((event.type == SDL_DROPFILE) || (event.type == SDL_DROPTEXT)) {
+                const char *typestr = (event.type == SDL_DROPFILE) ? "File" : "Text";
                 char *dropped_filedir = event.drop.file;
-                SDL_Log("File dropped on window: %s", dropped_filedir);
+                SDL_Log("%s dropped on window: %s", typestr, dropped_filedir);
                 SDL_free(dropped_filedir);
             }
         }