Просмотр исходного кода

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.
Ryan C. Gordon 10 лет назад
Родитель
Сommit
f9b7379341

+ 1 - 0
include/SDL_events.h

@@ -136,6 +136,7 @@ typedef enum
 
     /* 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 */

+ 19 - 6
src/events/SDL_dropevents.c

@@ -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: */

+ 1 - 0
src/events/SDL_dropevents_c.h

@@ -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 */
 

+ 14 - 30
src/video/x11/SDL_x11events.c

@@ -117,7 +117,9 @@ static Atom X11_PickTarget(Display *disp, Atom list[], int list_count)
     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_DispatchEvent(_THIS)
                 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;
-                            }
-                            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);
+                    /* !!! 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);
                             }
-                            expect_lf = SDL_FALSE;
-                            start = NULL;
                         }
-                        scan++;
+                        token = strtok(NULL, "\r\n");
                     }
                 }
 

+ 3 - 2
test/testdropfile.c

@@ -77,9 +77,10 @@ main(int argc, char *argv[])
         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);
             }
         }