Sfoglia il codice sorgente

Add the source application for drag and drop events (thanks Nathan!)

This is only implemented on iOS, but is useful for third party application integrations.

Fixes https://github.com/libsdl-org/SDL/issues/2024
Sam Lantinga 2 anni fa
parent
commit
91f0456391

+ 1 - 0
include/SDL3/SDL_events.h

@@ -523,6 +523,7 @@ typedef struct SDL_DropEvent
     SDL_WindowID windowID;    /**< The window that was dropped on, if any */
     SDL_WindowID windowID;    /**< The window that was dropped on, if any */
     float x;            /**< X coordinate, relative to window (not on begin) */
     float x;            /**< X coordinate, relative to window (not on begin) */
     float y;            /**< Y coordinate, relative to window (not on begin) */
     float y;            /**< Y coordinate, relative to window (not on begin) */
+    char *source;       /**< The source app that sent this drop event, or NULL if that isn't available */
     char *data;         /**< The text for SDL_EVENT_DROP_TEXT and the file name for SDL_EVENT_DROP_FILE, NULL for other events */
     char *data;         /**< The text for SDL_EVENT_DROP_TEXT and the file name for SDL_EVENT_DROP_FILE, NULL for other events */
     char short_data[SDL_DROPEVENT_DATA_SIZE]; /**< Memory space for short data, use 'data' instead */
     char short_data[SDL_DROPEVENT_DATA_SIZE]; /**< Memory space for short data, use 'data' instead */
 } SDL_DropEvent;
 } SDL_DropEvent;

+ 1 - 1
src/core/android/SDL_android.c

@@ -878,7 +878,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeDropFile)(
     jstring filename)
     jstring filename)
 {
 {
     const char *path = (*env)->GetStringUTFChars(env, filename, NULL);
     const char *path = (*env)->GetStringUTFChars(env, filename, NULL);
-    SDL_SendDropFile(NULL, path);
+    SDL_SendDropFile(NULL, NULL, path);
     (*env)->ReleaseStringUTFChars(env, filename, path);
     (*env)->ReleaseStringUTFChars(env, filename, path);
     SDL_SendDropComplete(NULL);
     SDL_SendDropComplete(NULL);
 }
 }

+ 1 - 1
src/core/haiku/SDL_BeApp.cc

@@ -69,7 +69,7 @@ public:
         entry_ref entryRef;
         entry_ref entryRef;
         for (int32 i = 0; message->FindRef("refs", i, &entryRef) == B_OK; i++) {
         for (int32 i = 0; message->FindRef("refs", i, &entryRef) == B_OK; i++) {
             BPath referencePath = BPath(&entryRef);
             BPath referencePath = BPath(&entryRef);
-            SDL_SendDropFile(NULL, referencePath.Path());
+            SDL_SendDropFile(NULL, NULL, referencePath.Path());
         }
         }
         return;
         return;
     }
     }

+ 10 - 8
src/events/SDL_dropevents.c

@@ -27,7 +27,7 @@
 
 
 #include "../video/SDL_sysvideo.h" /* for SDL_Window internals. */
 #include "../video/SDL_sysvideo.h" /* for SDL_Window internals. */
 
 
-static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const char *data, float x, float y)
+static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const char *source, const char *data, float x, float y)
 {
 {
     static SDL_bool app_is_dropping = SDL_FALSE;
     static SDL_bool app_is_dropping = SDL_FALSE;
     static float last_drop_x = 0;
     static float last_drop_x = 0;
@@ -58,6 +58,9 @@ static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const ch
         SDL_zero(event);
         SDL_zero(event);
         event.type = evtype;
         event.type = evtype;
         event.common.timestamp = 0;
         event.common.timestamp = 0;
+        if (source) {
+            event.drop.source = SDL_strdup(source);
+        }
         if (data) {
         if (data) {
             size_t len = SDL_strlen(data);
             size_t len = SDL_strlen(data);
             if (len < sizeof(event.drop.short_data)) {
             if (len < sizeof(event.drop.short_data)) {
@@ -91,23 +94,22 @@ static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const ch
     return posted;
     return posted;
 }
 }
 
 
-int SDL_SendDropFile(SDL_Window *window, const char *file)
+int SDL_SendDropFile(SDL_Window *window, const char *source, const char *file)
 {
 {
-    return SDL_SendDrop(window, SDL_EVENT_DROP_FILE, file, 0, 0);
+    return SDL_SendDrop(window, SDL_EVENT_DROP_FILE, source, file, 0, 0);
 }
 }
 
 
-int SDL_SendDropPosition(SDL_Window *window, const char *file, float x, float y)
+int SDL_SendDropPosition(SDL_Window *window, float x, float y)
 {
 {
-    /* Don't send 'file' since this is an malloc per position, which may be forgotten to be freed */
-    return SDL_SendDrop(window, SDL_EVENT_DROP_POSITION, NULL, x, y);
+    return SDL_SendDrop(window, SDL_EVENT_DROP_POSITION, NULL, NULL, x, y);
 }
 }
 
 
 int SDL_SendDropText(SDL_Window *window, const char *text)
 int SDL_SendDropText(SDL_Window *window, const char *text)
 {
 {
-    return SDL_SendDrop(window, SDL_EVENT_DROP_TEXT, text, 0, 0);
+    return SDL_SendDrop(window, SDL_EVENT_DROP_TEXT, NULL, text, 0, 0);
 }
 }
 
 
 int SDL_SendDropComplete(SDL_Window *window)
 int SDL_SendDropComplete(SDL_Window *window)
 {
 {
-    return SDL_SendDrop(window, SDL_EVENT_DROP_COMPLETE, NULL, 0, 0);
+    return SDL_SendDrop(window, SDL_EVENT_DROP_COMPLETE, NULL, NULL, 0, 0);
 }
 }

+ 2 - 2
src/events/SDL_dropevents_c.h

@@ -23,8 +23,8 @@
 #ifndef SDL_dropevents_c_h_
 #ifndef SDL_dropevents_c_h_
 #define SDL_dropevents_c_h_
 #define SDL_dropevents_c_h_
 
 
-extern int SDL_SendDropFile(SDL_Window *window, const char *file);
-extern int SDL_SendDropPosition(SDL_Window *window, const char *file, float x, float y);
+extern int SDL_SendDropFile(SDL_Window *window, const char *source, const char *file);
+extern int SDL_SendDropPosition(SDL_Window *window, float x, float y);
 extern int SDL_SendDropText(SDL_Window *window, const char *text);
 extern int SDL_SendDropText(SDL_Window *window, const char *text);
 extern int SDL_SendDropComplete(SDL_Window *window);
 extern int SDL_SendDropComplete(SDL_Window *window);
 
 

+ 4 - 0
src/events/SDL_events.c

@@ -1073,6 +1073,10 @@ void SDL_CleanupEvent(SDL_Event *event)
     switch (event->type) {
     switch (event->type) {
     case SDL_EVENT_DROP_FILE:
     case SDL_EVENT_DROP_FILE:
     case SDL_EVENT_DROP_TEXT:
     case SDL_EVENT_DROP_TEXT:
+        if (event->drop.source) {
+            SDL_free(event->drop.source);
+            event->drop.data = NULL;
+        }
         if (event->drop.data && event->drop.data != event->drop.short_data) {
         if (event->drop.data && event->drop.data != event->drop.short_data) {
             SDL_free(event->drop.data);
             SDL_free(event->drop.data);
             event->drop.data = NULL;
             event->drop.data = NULL;

+ 2 - 2
src/video/cocoa/SDL_cocoaevents.m

@@ -287,7 +287,7 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
 
 
 - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
 - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
 {
 {
-    return (BOOL)SDL_SendDropFile(NULL, [filename UTF8String]) && SDL_SendDropComplete(NULL);
+    return (BOOL)SDL_SendDropFile(NULL, NULL, [filename UTF8String]) && SDL_SendDropComplete(NULL);
 }
 }
 
 
 - (void)applicationDidFinishLaunching:(NSNotification *)notification
 - (void)applicationDidFinishLaunching:(NSNotification *)notification
@@ -315,7 +315,7 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
 - (void)handleURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
 - (void)handleURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
 {
 {
     NSString *path = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
     NSString *path = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
-    SDL_SendDropFile(NULL, [path UTF8String]);
+    SDL_SendDropFile(NULL, NULL, [path UTF8String]);
     SDL_SendDropComplete(NULL);
     SDL_SendDropComplete(NULL);
 }
 }
 
 

+ 2 - 2
src/video/cocoa/SDL_cocoawindow.m

@@ -177,7 +177,7 @@
         float x, y;
         float x, y;
         x = point.x;
         x = point.x;
         y = (sdlwindow->h - point.y);
         y = (sdlwindow->h - point.y);
-        SDL_SendDropPosition(sdlwindow, NULL, x, y); /* FIXME, should we get the filename */
+        SDL_SendDropPosition(sdlwindow, x, y);
         return NSDragOperationGeneric;
         return NSDragOperationGeneric;
     }
     }
 
 
@@ -242,7 +242,7 @@
                 }
                 }
             }
             }
 
 
-            if (!SDL_SendDropFile(sdlwindow, [[fileURL path] UTF8String])) {
+            if (!SDL_SendDropFile(sdlwindow, NULL, [[fileURL path] UTF8String])) {
                 return NO;
                 return NO;
             }
             }
         }
         }

+ 8 - 7
src/video/uikit/SDL_uikitappdelegate.m

@@ -212,7 +212,7 @@ static UIImage *SDL_LoadLaunchImageNamed(NSString *name, int screenh)
         NSArray *launchimages = [bundle objectForInfoDictionaryKey:@"UILaunchImages"];
         NSArray *launchimages = [bundle objectForInfoDictionaryKey:@"UILaunchImages"];
         NSString *imagename = nil;
         NSString *imagename = nil;
         UIImage *image = nil;
         UIImage *image = nil;
-        
+
 #if TARGET_OS_XR
 #if TARGET_OS_XR
         int screenw = SDL_XR_SCREENWIDTH;
         int screenw = SDL_XR_SCREENWIDTH;
         int screenh = SDL_XR_SCREENHEIGHT;
         int screenh = SDL_XR_SCREENHEIGHT;
@@ -221,7 +221,7 @@ static UIImage *SDL_LoadLaunchImageNamed(NSString *name, int screenh)
         int screenh = (int)([UIScreen mainScreen].bounds.size.height + 0.5);
         int screenh = (int)([UIScreen mainScreen].bounds.size.height + 0.5);
 #endif
 #endif
 
 
-       
+
 
 
 #if !TARGET_OS_TV && !TARGET_OS_XR
 #if !TARGET_OS_TV && !TARGET_OS_XR
         UIInterfaceOrientation curorient = [UIApplication sharedApplication].statusBarOrientation;
         UIInterfaceOrientation curorient = [UIApplication sharedApplication].statusBarOrientation;
@@ -505,13 +505,14 @@ static UIImage *SDL_LoadLaunchImageNamed(NSString *name, int screenh)
     /* Do nothing. */
     /* Do nothing. */
 }
 }
 
 
-- (void)sendDropFileForURL:(NSURL *)url
+- (void)sendDropFileForURL:(NSURL *)url fromSourceApplication:(NSString *)sourceApplication
 {
 {
     NSURL *fileURL = url.filePathURL;
     NSURL *fileURL = url.filePathURL;
+    char *sourceApplicationCString = sourceApplication ? [sourceApplication UTF8String] : NULL;
     if (fileURL != nil) {
     if (fileURL != nil) {
-        SDL_SendDropFile(NULL, fileURL.path.UTF8String);
+        SDL_SendDropFile(NULL, sourceApplicationCString, fileURL.path.UTF8String);
     } else {
     } else {
-        SDL_SendDropFile(NULL, url.absoluteString.UTF8String);
+        SDL_SendDropFile(NULL, sourceApplicationCString, url.absoluteString.UTF8String);
     }
     }
     SDL_SendDropComplete(NULL);
     SDL_SendDropComplete(NULL);
 }
 }
@@ -521,7 +522,7 @@ static UIImage *SDL_LoadLaunchImageNamed(NSString *name, int screenh)
 - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
 - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
 {
 {
     /* TODO: Handle options */
     /* TODO: Handle options */
-    [self sendDropFileForURL:url];
+    [self sendDropFileForURL:url fromSourceApplication:NULL];
     return YES;
     return YES;
 }
 }
 
 
@@ -529,7 +530,7 @@ static UIImage *SDL_LoadLaunchImageNamed(NSString *name, int screenh)
 
 
 - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
 - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
 {
 {
-    [self sendDropFileForURL:url];
+    [self sendDropFileForURL:url fromSourceApplication:sourceApplication];
     return YES;
     return YES;
 }
 }
 
 

+ 3 - 3
src/video/wayland/SDL_waylandevents.c

@@ -1909,7 +1909,7 @@ static void data_device_handle_motion(void *data, struct wl_data_device *wl_data
          *      Any future implementation should cache the filenames, as otherwise this could
          *      Any future implementation should cache the filenames, as otherwise this could
          *      hammer the DBus interface hundreds or even thousands of times per second.
          *      hammer the DBus interface hundreds or even thousands of times per second.
          */
          */
-        SDL_SendDropPosition(data_device->dnd_window, NULL, dx, dy);
+        SDL_SendDropPosition(data_device->dnd_window, dx, dy);
     }
     }
 }
 }
 
 
@@ -2055,7 +2055,7 @@ static void data_device_handle_drop(void *data, struct wl_data_device *wl_data_d
                     /* If dropped files contain a directory the list is empty */
                     /* If dropped files contain a directory the list is empty */
                     if (paths && path_count > 0) {
                     if (paths && path_count > 0) {
                         for (int i = 0; i < path_count; i++) {
                         for (int i = 0; i < path_count; i++) {
-                            SDL_SendDropFile(data_device->dnd_window, paths[i]);
+                            SDL_SendDropFile(data_device->dnd_window, NULL, paths[i]);
                         }
                         }
                         dbus->free_string_array(paths);
                         dbus->free_string_array(paths);
                         SDL_SendDropComplete(data_device->dnd_window);
                         SDL_SendDropComplete(data_device->dnd_window);
@@ -2080,7 +2080,7 @@ static void data_device_handle_drop(void *data, struct wl_data_device *wl_data_d
                 while (token != NULL) {
                 while (token != NULL) {
                     char *fn = Wayland_URIToLocal(token);
                     char *fn = Wayland_URIToLocal(token);
                     if (fn) {
                     if (fn) {
-                        SDL_SendDropFile(data_device->dnd_window, fn);
+                        SDL_SendDropFile(data_device->dnd_window, NULL, fn);
                     }
                     }
                     token = SDL_strtok_r(NULL, "\r\n", &saveptr);
                     token = SDL_strtok_r(NULL, "\r\n", &saveptr);
                 }
                 }

+ 1 - 1
src/video/windows/SDL_windowsevents.c

@@ -1478,7 +1478,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
             if (buffer) {
             if (buffer) {
                 if (DragQueryFile(drop, i, buffer, size)) {
                 if (DragQueryFile(drop, i, buffer, size)) {
                     char *file = WIN_StringToUTF8(buffer);
                     char *file = WIN_StringToUTF8(buffer);
-                    SDL_SendDropFile(data->window, file);
+                    SDL_SendDropFile(data->window, NULL, file);
                     SDL_free(file);
                     SDL_free(file);
                 }
                 }
                 SDL_small_free(buffer, isstack);
                 SDL_small_free(buffer, isstack);

+ 2 - 2
src/video/x11/SDL_x11events.c

@@ -1327,7 +1327,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
                 X11_XTranslateCoordinates(display, DefaultRootWindow(display), data->xwindow,
                 X11_XTranslateCoordinates(display, DefaultRootWindow(display), data->xwindow,
                         root_x, root_y, &window_x, &window_y, &ChildReturn);
                         root_x, root_y, &window_x, &window_y, &ChildReturn);
 
 
-                SDL_SendDropPosition(data->window, NULL, (float)window_x, (float)window_y); /* FIXME, can we get the filename ? */
+                SDL_SendDropPosition(data->window, (float)window_x, (float)window_y);
             }
             }
 
 
             /* reply with status */
             /* reply with status */
@@ -1629,7 +1629,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
                         } else if (SDL_strcmp("text/uri-list", name) == 0) {
                         } else if (SDL_strcmp("text/uri-list", name) == 0) {
                             char *fn = X11_URIToLocal(token);
                             char *fn = X11_URIToLocal(token);
                             if (fn) {
                             if (fn) {
-                                SDL_SendDropFile(data->window, fn);
+                                SDL_SendDropFile(data->window, NULL, fn);
                             }
                             }
                         }
                         }
                         token = SDL_strtok_r(NULL, "\r\n", &saveptr);
                         token = SDL_strtok_r(NULL, "\r\n", &saveptr);