From f9b7379341fc241e7e2daf2811394956fed1ba61 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 5 Jan 2016 02:26:45 -0500 Subject: [PATCH] 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 | 1 + src/events/SDL_dropevents.c | 25 +++++++++++++++----- src/events/SDL_dropevents_c.h | 1 + src/video/x11/SDL_x11events.c | 44 +++++++++++------------------------ test/testdropfile.c | 5 ++-- 5 files changed, 38 insertions(+), 38 deletions(-) diff --git a/include/SDL_events.h b/include/SDL_events.h index 1437f4c7053a9..04d6d88d1530f 100644 --- a/include/SDL_events.h +++ b/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 */ diff --git a/src/events/SDL_dropevents.c b/src/events/SDL_dropevents.c index 8f4405efa4ed3..ff68d7d20988e 100644 --- a/src/events/SDL_dropevents.c +++ b/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: */ diff --git a/src/events/SDL_dropevents_c.h b/src/events/SDL_dropevents_c.h index a60e089f35eed..73ca139946ba3 100644 --- a/src/events/SDL_dropevents_c.h +++ b/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 */ diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index e69111cb90c4b..0cfc37b56b609 100644 --- a/src/video/x11/SDL_x11events.c +++ b/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"); } } diff --git a/test/testdropfile.c b/test/testdropfile.c index b7f215ee814b9..85d6a80fa5fb6 100644 --- a/test/testdropfile.c +++ b/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); } }