Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDL_DragEvent: Add SDL_DragEvents #13

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
# esy-sdl2
Esy-enabled build for [SDL2](https://www.libsdl.org/)

# Modifications
## Modifications

A patch by xenotron007 was applied to enable Windows IME candidate list to be shown:
https://bugzilla.libsdl.org/attachment.cgi?id=3604&action=diff
- A patch by xenotron007 was applied to enable Windows IME candidate list to be shown: https://bugzilla.libsdl.org/attachment.cgi?id=3604&action=diff
- A patch by [@zbaylin](https://github.com/zbaylin) was made to add drag events that closely mirror the built-in drop events

# License

## License

[SDL License](./LICENSE)
18 changes: 17 additions & 1 deletion include/SDL_events.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,12 @@ typedef enum
/* Pan events */
SDL_PANEVENT = 0x2100,

/* Drag events */
SDL_DRAGFILE = 0x2200,
SDL_DRAGTEXT,
SDL_DRAGBEGIN,
SDL_DRAGCOMPLETE,

/** Events ::SDL_USEREVENT through ::SDL_LASTEVENT are for your use,
* and should be allocated with SDL_RegisterEvents()
*/
Expand Down Expand Up @@ -533,6 +539,16 @@ typedef struct SDL_DropEvent
} SDL_DropEvent;


typedef struct SDL_DragEvent
{
Uint32 type;
Uint32 timestamp;
char *file;
Uint32 windowID;
Sint32 x;
Sint32 y;
} SDL_DragEvent;

/**
* \brief Sensor event structure (event.sensor.*)
*/
Expand Down Expand Up @@ -624,7 +640,7 @@ typedef union SDL_Event
SDL_MultiGestureEvent mgesture; /**< Gesture event data */
SDL_DollarGestureEvent dgesture; /**< Gesture event data */
SDL_DropEvent drop; /**< Drag and drop event data */

SDL_DragEvent drag;
SDL_PanEvent pan; /**< Obsolesces mouse wheel events */

/* This is necessary for ABI compatibility between Visual C++ and GCC
Expand Down
64 changes: 64 additions & 0 deletions src/events/SDL_dragevents.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "../SDL_internal.h"

#include "SDL_events.h"
#include "SDL_events_c.h"
#include "SDL_dragevents_c.h"

#include "../video/SDL_sysvideo.h" /* for SDL_Window internals. */

const int
SDL_SendDrag(SDL_Window *window, const SDL_EventType evtype, const char *data, int x, int y)
zbaylin marked this conversation as resolved.
Show resolved Hide resolved
{
static SDL_bool app_is_dragging = SDL_FALSE;
int posted = 0;

const SDL_bool need_begin = window ? !window->is_dragging : !app_is_dragging;
SDL_Event event;

if (need_begin) {
SDL_zero(event);
event.type = SDL_DRAGBEGIN;
event.drag.x = x;
event.drag.y = y;

if (window) {
event.drag.windowID = window->id;
}

posted = (SDL_PushEvent(&event) > 0);
if (!posted) {
return 0;
}
Comment on lines +28 to +31
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assignment seems unnecessary, and a bit confusing. I'd expect posted to be read from again later, but it isn't. So it would be simpler to just check the result directly I think:

Suggested change
posted = (SDL_PushEvent(&event) > 0);
if (!posted) {
return 0;
}
if (SDL_PushEvent(&event) == 0) {
return 0;
}

if (window) {
window->is_dragging = SDL_TRUE;
} else {
app_is_dragging = SDL_TRUE;
}
}

SDL_zero(event);
event.type = evtype;
event.drag.file = data ? SDL_strdup(data) : NULL;
event.drag.windowID = window ? window->id : 0;
event.drag.x = x;
event.drag.y = y;
posted = (SDL_PushEvent(&event) > 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

posted is an ambiguous name. It's not immediately obvious whether it refers to a boolean or a count of items posted, for example. Therefore I prefer using isPosted for booleans.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. All the variable names I used I either borrowed from other functions (see SDL_dropevents.c) or modeled them closely after others. In this case it doesn't matter because I can remove the posted reference altogether though!


if (posted && (evtype == SDL_DRAGCOMPLETE)) {
if (window) {
window->is_dragging = SDL_FALSE;
} else {
app_is_dragging = SDL_FALSE;
}
}
return posted;
}

int SDL_SendDragFile(SDL_Window *window, const char *file, int x, int y)
{
return SDL_SendDrag(window, SDL_DRAGFILE, file, x, y);
}

int SDL_SendDragComplete(SDL_Window *window, int x, int y) {
return SDL_SendDrag(window, SDL_DRAGCOMPLETE, NULL, x, y);
}
8 changes: 8 additions & 0 deletions src/events/SDL_dragevents_c.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#include "../SDL_internal.h"

#ifndef SDL_dragevents_c_h_
#define SDL_dragevents_c_h_

extern int SDL_SendDragFile(SDL_Window *window, const char *file, int x, int y);
extern int SDL_SendDragComplete(SDL_Window *window, int x, int y);
#endif
1 change: 1 addition & 0 deletions src/events/SDL_events_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#include "SDL_clipboardevents_c.h"
#include "SDL_displayevents_c.h"
#include "SDL_dragevents_c.h"
#include "SDL_dropevents_c.h"
#include "SDL_gesture_c.h"
#include "SDL_keyboard_c.h"
Expand Down
1 change: 1 addition & 0 deletions src/video/SDL_sysvideo.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ struct SDL_Window
SDL_bool is_hiding;
SDL_bool is_destroying;
SDL_bool is_dropping; /* drag/drop in progress, expecting SDL_SendDropComplete(). */
SDL_bool is_dragging;

SDL_WindowShaper *shaper;

Expand Down
52 changes: 52 additions & 0 deletions src/video/cocoa/SDL_cocoawindow.m
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "../../events/SDL_mouse_c.h"
#include "../../events/SDL_touch_c.h"
#include "../../events/SDL_windowevents_c.h"
#include "../../events/SDL_dragevents_c.h"
#include "../../events/SDL_dropevents_c.h"
#include "SDL_cocoavideo.h"
#include "SDL_cocoashape.h"
Expand Down Expand Up @@ -139,6 +140,57 @@ - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
return NSDragOperationNone; /* no idea what to do with this, reject it. */
}

- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender
{
NSPasteboard *pasteboard = [sender draggingPasteboard];
NSArray *types = [NSArray arrayWithObject:NSFilenamesPboardType];
NSString *desiredType = [pasteboard availableTypeFromArray:types];
SDL_Window *sdlwindow = [self findSDLWindow];
NSPoint point = [sender draggingLocation];

if (desiredType == nil) {
return NSDragOperationNone;
}

NSData *data = [pasteboard dataForType:desiredType];
if (data == nil) {
return NSDragOperationNone;
}

SDL_assert([desiredType isEqualToString:NSFilenamesPboardType]);
NSArray *array = [pasteboard propertyListForType:@"NSFilenamesPboardType"];

for (NSString *path in array) {
NSURL *fileURL = [NSURL fileURLWithPath:path];
NSNumber *isAlias = nil;

[fileURL getResourceValue:&isAlias forKey:NSURLIsAliasFileKey error:nil];

if ([isAlias boolValue]) {
NSURLBookmarkResolutionOptions opts = NSURLBookmarkResolutionWithoutMounting | NSURLBookmarkResolutionWithoutUI;
NSData *bookmark = [NSURL bookmarkDataWithContentsOfURL:fileURL error:nil];
if (bookmark != nil) {
NSURL *resolvedURL = [NSURL URLByResolvingBookmarkData:bookmark
options:opts
relativeToURL:nil
bookmarkDataIsStale:nil
error:nil];

if (resolvedURL != nil) {
fileURL = resolvedURL;
}
}
}

if (!SDL_SendDragFile(sdlwindow, [[fileURL path] UTF8String], point.x, point.y)) {
return NSDragOperationNone;
}
}

SDL_SendDragComplete(sdlwindow, point.x, point.y);
return NSDragOperationGeneric;
}

- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
{ @autoreleasepool
{
Expand Down
71 changes: 57 additions & 14 deletions src/video/x11/SDL_x11events.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include "SDL_x11video.h"
#include "SDL_x11touch.h"
#include "SDL_x11mouse.h"
#include "SDL_x11xinput2.h"
#include "../../core/unix/SDL_poll.h"
#include "../../events/SDL_events_c.h"
Expand Down Expand Up @@ -982,7 +983,7 @@ X11_DispatchEvent(_THIS)
&xevent.xconfigure.x, &xevent.xconfigure.y,
&ChildReturn);
}

if (xevent.xconfigure.x != data->last_xconfigure.x ||
xevent.xconfigure.y != data->last_xconfigure.y) {
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED,
Expand Down Expand Up @@ -1057,6 +1058,26 @@ X11_DispatchEvent(_THIS)
m.data.l[4] = videodata->XdndActionCopy; /* we only accept copying anyway */

X11_XSendEvent(display, xevent.xclient.data.l[0], False, NoEventMask, (XEvent*)&m);

if (data->xdnd_req == None) {
memset(&m, 0, sizeof(XClientMessageEvent));
m.type = ClientMessage;
m.display = xevent.xclient.display;
m.window = xevent.xclient.data.l[0];
m.message_type = videodata->XdndFinished;
m.format=32;
m.data.l[0] = data->xwindow;
m.data.l[1] = 0;
m.data.l[2] = None; /* fail! */
X11_XSendEvent(display, xevent.xclient.data.l[0], False, NoEventMask, (XEvent*)&m);
} else {
data->dragging = SDL_TRUE;
if(xdnd_version >= 1) {
X11_XConvertSelection(display, videodata->XdndSelection, data->xdnd_req, videodata->PRIMARY, data->xwindow, xevent.xclient.data.l[2]);
} else {
X11_XConvertSelection(display, videodata->XdndSelection, data->xdnd_req, videodata->PRIMARY, data->xwindow, CurrentTime);
}
}
X11_XFlush(display);
}
else if(xevent.xclient.message_type == videodata->XdndDrop) {
Expand All @@ -1074,6 +1095,7 @@ X11_DispatchEvent(_THIS)
X11_XSendEvent(display, xevent.xclient.data.l[0], False, NoEventMask, (XEvent*)&m);
} else {
/* convert */
data->dropping = SDL_TRUE;
if(xdnd_version >= 1) {
X11_XConvertSelection(display, videodata->XdndSelection, data->xdnd_req, videodata->PRIMARY, data->xwindow, xevent.xclient.data.l[2]);
} else {
Expand Down Expand Up @@ -1342,39 +1364,60 @@ X11_DispatchEvent(_THIS)
#endif
if (target == data->xdnd_req) {
/* read data */
SDL_Mouse *mouse = SDL_GetMouse();
SDL_x11Prop p;
int globalMouseX, globalMouseY, localMouseX, localMouseY;

X11_ReadProperty(&p, display, data->xwindow, videodata->PRIMARY);

if (p.format == 8) {
/* !!! 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");
if (data->dragging) {
mouse->GetGlobalMouseState(&globalMouseX, &globalMouseY);
localMouseX = globalMouseX - data->window->x;
localMouseY = globalMouseY - data->window->y;
}
while (token != NULL) {
if (SDL_strcmp("text/plain", name)==0) {
SDL_SendDropText(data->window, token);
} else if (SDL_strcmp("text/uri-list", name)==0) {
char *fn = X11_URIToLocal(token);
if (fn) {
SDL_SendDropFile(data->window, fn);
if (data->dropping) {
SDL_SendDropFile(data->window, fn);
} else if (data->dragging) {
SDL_SendDragFile(data->window, fn, localMouseX, localMouseY);
}
}
}
token = strtok(NULL, "\r\n");
}
SDL_SendDropComplete(data->window);
if (data->dropping) {
SDL_SendDropComplete(data->window);
} else if (data->dragging) {
SDL_SendDragComplete(data->window, localMouseX, localMouseY);
}
}
X11_XFree(p.data);

/* send reply */
SDL_memset(&m, 0, sizeof(XClientMessageEvent));
m.type = ClientMessage;
m.display = display;
m.window = data->xdnd_source;
m.message_type = videodata->XdndFinished;
m.format = 32;
m.data.l[0] = data->xwindow;
m.data.l[1] = 1;
m.data.l[2] = videodata->XdndActionCopy;
X11_XSendEvent(display, data->xdnd_source, False, NoEventMask, (XEvent*)&m);
if (data->dropping) {
/* send reply */
SDL_memset(&m, 0, sizeof(XClientMessageEvent));
m.type = ClientMessage;
m.display = display;
m.window = data->xdnd_source;
m.message_type = videodata->XdndFinished;
m.format = 32;
m.data.l[0] = data->xwindow;
m.data.l[1] = 1;
m.data.l[2] = videodata->XdndActionCopy;
X11_XSendEvent(display, data->xdnd_source, False, NoEventMask, (XEvent*)&m);
}

data->dragging = SDL_FALSE;
data->dropping = SDL_FALSE;

X11_XSync(display, False);
}
Expand Down
6 changes: 4 additions & 2 deletions src/video/x11/SDL_x11window.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
*/
#define PENDING_FOCUS_TIME 200

#if SDL_VIDEO_OPENGL_EGL
#if SDL_VIDEO_OPENGL_EGL
#include <EGL/egl.h>
#endif

Expand Down Expand Up @@ -67,8 +67,10 @@ typedef struct
struct SDL_VideoData *videodata;
unsigned long user_time;
Atom xdnd_req;
SDL_bool dragging;
SDL_bool dropping;
Comment on lines +70 to +71
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here:

Suggested change
SDL_bool dragging;
SDL_bool dropping;
SDL_bool isDragging;
SDL_bool isDropping;

Window xdnd_source;
#if SDL_VIDEO_OPENGL_EGL
#if SDL_VIDEO_OPENGL_EGL
EGLSurface egl_surface;
#endif
} SDL_WindowData;
Expand Down