Add Drag and drop position, for x11, wayland and MACOSX

main
Sylvain 2023-03-06 11:16:18 +01:00 committed by Sam Lantinga
parent 813c586edb
commit a946a34452
7 changed files with 112 additions and 15 deletions

View File

@ -172,6 +172,7 @@ typedef enum
SDL_EVENT_DROP_TEXT, /**< text/plain drag-and-drop event */
SDL_EVENT_DROP_BEGIN, /**< A new set of drops is beginning (NULL filename) */
SDL_EVENT_DROP_COMPLETE, /**< Current set of drops is now complete (NULL filename) */
SDL_EVENT_DROP_POSITION, /**< Position while moving over the window */
/* Audio hotplug events */
SDL_EVENT_AUDIO_DEVICE_ADDED = 0x1100, /**< A new audio device is available */
@ -515,10 +516,12 @@ typedef struct SDL_TouchFingerEvent
*/
typedef struct SDL_DropEvent
{
Uint32 type; /**< ::SDL_EVENT_DROP_BEGIN or ::SDL_EVENT_DROP_FILE or ::SDL_EVENT_DROP_TEXT or ::SDL_EVENT_DROP_COMPLETE */
Uint32 type; /**< ::SDL_EVENT_DROP_BEGIN or ::SDL_EVENT_DROP_FILE or ::SDL_EVENT_DROP_TEXT or ::SDL_EVENT_DROP_COMPLETE or ::SDL_EVENT_DROP_POSITION */
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
char *file; /**< The file name, which should be freed with SDL_free(), is NULL on begin/complete */
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 y; /**< Y coordinate, relative to window (not on begin) */
} SDL_DropEvent;

View File

@ -27,9 +27,11 @@
#include "../video/SDL_sysvideo.h" /* for SDL_Window internals. */
static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const char *data)
static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const char *data, float x, float y)
{
static SDL_bool app_is_dropping = SDL_FALSE;
static float last_drop_x = 0;
static float last_drop_y = 0;
int posted = 0;
/* Post the event, if desired */
@ -58,6 +60,13 @@ static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const ch
event.common.timestamp = 0;
event.drop.file = data ? SDL_strdup(data) : NULL;
event.drop.windowID = window ? window->id : 0;
if (evtype == SDL_EVENT_DROP_POSITION) {
last_drop_x = x;
last_drop_y = y;
}
event.drop.x = last_drop_x;
event.drop.y = last_drop_y;
posted = (SDL_PushEvent(&event) > 0);
if (posted && (evtype == SDL_EVENT_DROP_COMPLETE)) {
@ -66,6 +75,9 @@ static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const ch
} else {
app_is_dropping = SDL_FALSE;
}
last_drop_x = 0;
last_drop_y = 0;
}
}
return posted;
@ -73,15 +85,21 @@ static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const ch
int SDL_SendDropFile(SDL_Window *window, const char *file)
{
return SDL_SendDrop(window, SDL_EVENT_DROP_FILE, file);
return SDL_SendDrop(window, SDL_EVENT_DROP_FILE, file, 0, 0);
}
int SDL_SendDropPosition(SDL_Window *window, const char *file, 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);
}
int SDL_SendDropText(SDL_Window *window, const char *text)
{
return SDL_SendDrop(window, SDL_EVENT_DROP_TEXT, text);
return SDL_SendDrop(window, SDL_EVENT_DROP_TEXT, text, 0, 0);
}
int SDL_SendDropComplete(SDL_Window *window)
{
return SDL_SendDrop(window, SDL_EVENT_DROP_COMPLETE, NULL);
return SDL_SendDrop(window, SDL_EVENT_DROP_COMPLETE, NULL, 0, 0);
}

View File

@ -24,6 +24,7 @@
#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_SendDropText(SDL_Window *window, const char *text);
extern int SDL_SendDropComplete(SDL_Window *window);

View File

@ -85,6 +85,7 @@
/* Handle drag-and-drop of files onto the SDL window. */
- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender;
- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender;
- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender;
- (BOOL)wantsPeriodicDraggingUpdates;
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem;
@ -158,6 +159,21 @@
return NSDragOperationNone; /* no idea what to do with this, reject it. */
}
- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender
{
if (([sender draggingSourceOperationMask] & NSDragOperationGeneric) == NSDragOperationGeneric) {
SDL_Window *sdlwindow = [self findSDLWindow];
NSPoint point = [sender draggingLocation];
float x, y;
x = point.x;
y = (sdlwindow->h - point.y);
SDL_SendDropPosition(sdlwindow, NULL, x, y); /* FIXME, should we get the filename */
return NSDragOperationGeneric;
}
return NSDragOperationNone; /* no idea what to do with this, reject it. */
}
- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender
{
@autoreleasepool {

View File

@ -96,6 +96,8 @@ struct SDL_WaylandTouchPointList
static struct SDL_WaylandTouchPointList touch_points = { NULL, NULL };
static char *Wayland_URIToLocal(char *uri);
static void touch_add(SDL_TouchID id, float x, float y, struct wl_surface *surface)
{
struct SDL_WaylandTouchPoint *tp = SDL_malloc(sizeof(struct SDL_WaylandTouchPoint));
@ -1845,6 +1847,30 @@ static void data_device_handle_leave(void *data, struct wl_data_device *wl_data_
static void data_device_handle_motion(void *data, struct wl_data_device *wl_data_device,
uint32_t time, wl_fixed_t x, wl_fixed_t y)
{
SDL_WaylandDataDevice *data_device = data;
if (data_device->drag_offer != NULL) {
/* TODO: SDL Support more mime types */
size_t length;
void *buffer = Wayland_data_offer_receive(data_device->drag_offer,
&length, FILE_MIME, SDL_TRUE);
if (buffer) {
char *saveptr = NULL;
char *token = SDL_strtokr((char *)buffer, "\r\n", &saveptr);
while (token != NULL) {
char *fn = Wayland_URIToLocal(token);
if (fn) {
double dx;
double dy;
dx = wl_fixed_to_double(x);
dy = wl_fixed_to_double(y);
SDL_SendDropPosition(data_device->dnd_window, fn, (float)dx, (float)dy);
}
token = SDL_strtokr(NULL, "\r\n", &saveptr);
}
SDL_free(buffer);
}
}
}
/* Decodes URI escape sequences in string buf of len bytes

View File

@ -1222,6 +1222,18 @@ static void X11_DispatchEvent(_THIS, XEvent *xevent)
}
printf("Action requested by user is : %s\n", X11_XGetAtomName(display, act));
#endif
{
/* Drag and Drop position */
int root_x, root_y, window_x, window_y;
Window ChildReturn;
root_x = xevent->xclient.data.l[2] >> 16;
root_y = xevent->xclient.data.l[2] & 0xffff;
/* Translate from root to current window position */
X11_XTranslateCoordinates(display, DefaultRootWindow(display), data->xwindow,
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 ? */
}
/* reply with status */
SDL_memset(&m, 0, sizeof(XClientMessageEvent));

View File

@ -29,6 +29,9 @@ int main(int argc, char *argv[])
{
int i, done;
SDL_Event event;
SDL_bool is_hover = SDL_FALSE;
float x = 0.0f, y = 0.0f;
unsigned int windowID = 0;
/* Enable standard application logging */
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
@ -60,12 +63,6 @@ int main(int argc, char *argv[])
quit(2);
}
for (i = 0; i < state->num_windows; ++i) {
SDL_Renderer *renderer = state->renderers[i];
SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
SDL_SetEventEnabled(SDL_EVENT_DROP_FILE, SDL_TRUE);
@ -75,19 +72,43 @@ int main(int argc, char *argv[])
/* Check for events */
while (SDL_PollEvent(&event)) {
if (event.type == SDL_EVENT_DROP_BEGIN) {
SDL_Log("Drop beginning on window %u", (unsigned int)event.drop.windowID);
SDL_Log("Drop beginning on window %u at (%f, %f)", (unsigned int)event.drop.windowID, event.drop.x, event.drop.y);
} else if (event.type == SDL_EVENT_DROP_COMPLETE) {
SDL_Log("Drop complete on window %u", (unsigned int)event.drop.windowID);
is_hover = SDL_FALSE;
SDL_Log("Drop complete on window %u at (%f, %f)", (unsigned int)event.drop.windowID, event.drop.x, event.drop.y);
} else if ((event.type == SDL_EVENT_DROP_FILE) || (event.type == SDL_EVENT_DROP_TEXT)) {
const char *typestr = (event.type == SDL_EVENT_DROP_FILE) ? "File" : "Text";
char *dropped_filedir = event.drop.file;
SDL_Log("%s dropped on window %u: %s", typestr, (unsigned int)event.drop.windowID, dropped_filedir);
SDL_Log("%s dropped on window %u: %s at (%f, %f)", typestr, (unsigned int)event.drop.windowID, dropped_filedir, event.drop.x, event.drop.y);
/* Normally you'd have to do this, but this is freed in SDLTest_CommonEvent() */
/*SDL_free(dropped_filedir);*/
} else if (event.type == SDL_EVENT_DROP_POSITION) {
is_hover = SDL_TRUE;
x = event.drop.x;
y = event.drop.y;
windowID = event.drop.windowID;
SDL_Log("Drop position on window %u at (%f, %f) file = %s", (unsigned int)event.drop.windowID, event.drop.x, event.drop.y, event.drop.file);
}
SDLTest_CommonEvent(state, &event, &done);
}
for (i = 0; i < state->num_windows; ++i) {
SDL_Renderer *renderer = state->renderers[i];
SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
SDL_RenderClear(renderer);
if (is_hover) {
if (windowID == SDL_GetWindowID(SDL_GetRenderWindow(renderer))) {
int len = 2000;
SDL_SetRenderDrawColor(renderer, 0x0A, 0x0A, 0x0A, 0xFF);
SDL_RenderLine(renderer, x, y - len, x, y + len);
SDL_RenderLine(renderer, x - len, y, x + len, y);
}
}
SDL_RenderPresent(renderer);
}
SDL_Delay(16);
}
quit(0);