Merge branch 'feature-dnd' of github.com:arturoc/glfw into feature-dnd

This commit is contained in:
arturoc 2013-07-12 17:34:41 +02:00
commit 3ca9bb420a
4 changed files with 120 additions and 34 deletions

View File

@ -390,6 +390,8 @@ static int translateKey(unsigned int key)
@interface GLFWContentView : NSView @interface GLFWContentView : NSView
{ {
_GLFWwindow* window; _GLFWwindow* window;
char * fileNamesForDrag;
int fileNamesSize;
NSTrackingArea* trackingArea; NSTrackingArea* trackingArea;
} }
@ -420,8 +422,15 @@ static int translateKey(unsigned int key)
{ {
window = initWindow; window = initWindow;
trackingArea = nil; trackingArea = nil;
fileNamesForDrag = (char*)malloc(1024);
fileNamesSize = 1024;
[self updateTrackingAreas]; [self updateTrackingAreas];
[self registerForDraggedTypes:[NSArray arrayWithObjects:
NSFilenamesPboardType, nil]];
} }
return self; return self;
@ -430,6 +439,7 @@ static int translateKey(unsigned int key)
-(void)dealloc -(void)dealloc
{ {
[trackingArea release]; [trackingArea release];
free(fileNamesForDrag);
[super dealloc]; [super dealloc];
} }
@ -613,10 +623,70 @@ static int translateKey(unsigned int key)
_glfwInputScroll(window, deltaX, deltaY); _glfwInputScroll(window, deltaX, deltaY);
} }
- (void)resetCursorRects
// arturoc: this makes the cursor dissapear when the window is
// resized or received a drag operation
/*- (void)resetCursorRects
{ {
[self discardCursorRects]; [self discardCursorRects];
[self addCursorRect:[self bounds] cursor:_glfw.ns.cursor]; [self addCursorRect:[self bounds] cursor:_glfw.ns.cursor];
}*/
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
if ((NSDragOperationGeneric & [sender draggingSourceOperationMask])
== NSDragOperationGeneric) {
[self setNeedsDisplay:YES];
return NSDragOperationGeneric;
}
return NSDragOperationNone;
}
- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender {
[self setNeedsDisplay:YES];
return YES;
}
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender {
NSPasteboard *zPasteboard = [sender draggingPasteboard];
NSArray *files = [zPasteboard propertyListForType:NSFilenamesPboardType];
// set the first char to 0 so strcat
// starts to add from the beginning
fileNamesForDrag[0] = 0;
int dragX = [sender draggingLocation].x;
int dragY = [sender draggingLocation].y;
int dragSize = 1;
if ([files count]) {
NSEnumerator *filenameEnum = [files objectEnumerator];
NSString *name;
while (name = [filenameEnum nextObject]) {
dragSize += [name length]+1;
if (dragSize > fileNamesSize){
fileNamesSize *= 2;
fileNamesForDrag = realloc(fileNamesForDrag, fileNamesSize);
}
strcat(fileNamesForDrag, [name UTF8String]);
strcat(fileNamesForDrag, "\n");
}
}
int height;
_glfwPlatformGetWindowSize(window, NULL, &height);
_glfwInputCursorMotion(window, dragX, height-dragY);
_glfwInputDrop(window, fileNamesForDrag);
return YES;
}
- (void)concludeDragOperation:(id <NSDraggingInfo>)sender {
[self setNeedsDisplay:YES];
} }
@end @end

View File

@ -546,14 +546,11 @@ static GLboolean initExtensions(void)
_glfw.x11.XdndEnter = XInternAtom(_glfw.x11.display, "XdndEnter", False); _glfw.x11.XdndEnter = XInternAtom(_glfw.x11.display, "XdndEnter", False);
_glfw.x11.XdndPosition = XInternAtom(_glfw.x11.display, "XdndPosition", False); _glfw.x11.XdndPosition = XInternAtom(_glfw.x11.display, "XdndPosition", False);
_glfw.x11.XdndStatus = XInternAtom(_glfw.x11.display, "XdndStatus", False); _glfw.x11.XdndStatus = XInternAtom(_glfw.x11.display, "XdndStatus", False);
_glfw.x11.XdndTypeList = XInternAtom(_glfw.x11.display, "XdndTypeList", False);
_glfw.x11.XdndActionCopy = XInternAtom(_glfw.x11.display, "XdndActionCopy", False); _glfw.x11.XdndActionCopy = XInternAtom(_glfw.x11.display, "XdndActionCopy", False);
_glfw.x11.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", False); _glfw.x11.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", False);
_glfw.x11.XdndLeave = XInternAtom(_glfw.x11.display, "XdndLeave", False); _glfw.x11.XdndLeave = XInternAtom(_glfw.x11.display, "XdndLeave", False);
_glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", False); _glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", False);
_glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", False); _glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", False);
_glfw.x11.XdndProxy = XInternAtom(_glfw.x11.display, "XdndProxy", False);
_glfw.x11.XA_TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False);
_glfw.x11.xdnd.string = NULL; _glfw.x11.xdnd.string = NULL;
_glfw.x11.xdnd.type1 = NULL; _glfw.x11.xdnd.type1 = NULL;
_glfw.x11.xdnd.type2 = NULL; _glfw.x11.xdnd.type2 = NULL;

View File

@ -127,14 +127,11 @@ typedef struct _GLFWlibraryX11
Atom XdndEnter; Atom XdndEnter;
Atom XdndPosition; Atom XdndPosition;
Atom XdndStatus; Atom XdndStatus;
Atom XdndTypeList;
Atom XdndActionCopy; Atom XdndActionCopy;
Atom XdndDrop; Atom XdndDrop;
Atom XdndLeave; Atom XdndLeave;
Atom XdndFinished; Atom XdndFinished;
Atom XdndSelection; Atom XdndSelection;
Atom XdndProxy;
Atom XA_TARGETS;
struct{ struct{
Window sourceWindow; Window sourceWindow;
char* string; char* string;

View File

@ -714,20 +714,11 @@ static void processEvent(XEvent *event)
// the window, ask to convert the selection // the window, ask to convert the selection
_glfw.x11.xdnd.sourceWindow = event->xclient.data.l[0]; _glfw.x11.xdnd.sourceWindow = event->xclient.data.l[0];
XConvertSelection(_glfw.x11.display,
const Atom formats[] = { _glfw.x11.UTF8_STRING, _glfw.x11.XdndSelection,
_glfw.x11.COMPOUND_STRING, _glfw.x11.UTF8_STRING,
XA_STRING }; _glfw.x11.XdndSelection,
const int formatCount = sizeof(formats) / sizeof(formats[0]); window->x11.handle, CurrentTime);
int i;
for(i=0;i<formatCount;i++){
XConvertSelection(_glfw.x11.display,
_glfw.x11.XdndSelection,
formats[i],
_glfw.x11.XdndSelection,
window->x11.handle, CurrentTime);
}
} }
else if(event->xclient.message_type == _glfw.x11.XdndLeave) else if(event->xclient.message_type == _glfw.x11.XdndLeave)
@ -740,12 +731,14 @@ static void processEvent(XEvent *event)
// and update the mouse position // and update the mouse position
int absX = (event->xclient.data.l[2]>>16) & 0xFFFF; int absX = (event->xclient.data.l[2]>>16) & 0xFFFF;
int absY = (event->xclient.data.l[2]) & 0xFFFF; int absY = (event->xclient.data.l[2]) & 0xFFFF;
int x;
int y;
_glfwPlatformGetWindowPos(window,&x,&y); Window child;
int x, y;
_glfwInputCursorMotion(window,absX-x,absY-y); XTranslateCoordinates(_glfw.x11.display, _glfw.x11.root, window->x11.handle,
absX, absY, &x, &y, &child);
_glfwInputCursorMotion(window,x,y);
// Xdnd: reply with an XDND status message // Xdnd: reply with an XDND status message
XClientMessageEvent m; XClientMessageEvent m;
@ -763,7 +756,6 @@ static void processEvent(XEvent *event)
XSendEvent(_glfw.x11.display, event->xclient.data.l[0], False, NoEventMask, (XEvent*)&m); XSendEvent(_glfw.x11.display, event->xclient.data.l[0], False, NoEventMask, (XEvent*)&m);
XFlush(_glfw.x11.display); XFlush(_glfw.x11.display);
} }
break; break;
@ -776,13 +768,36 @@ static void processEvent(XEvent *event)
// Xdnd: got a selection notification from the conversion // Xdnd: got a selection notification from the conversion
// we asked for, get the data and finish the d&d event // we asked for, get the data and finish the d&d event
char* data; char* data;
_glfwGetWindowProperty(event->xselection.requestor, free(_glfw.x11.xdnd.string);
_glfw.x11.xdnd.string = NULL;
int result = _glfwGetWindowProperty(event->xselection.requestor,
event->xselection.property, event->xselection.property,
event->xselection.target, event->xselection.target,
(unsigned char**) &data); (unsigned char**) &data);
free(_glfw.x11.xdnd.string); if(result){
_glfw.x11.xdnd.string = strdup(data); // nautilus seems to add a \r at the end of the paths
// remove it so paths can be directly used
_glfw.x11.xdnd.string = malloc(strlen(data));
char *to = _glfw.x11.xdnd.string;
const char *from = data;
const char *current = strchr(from, '\r');
while(current)
{
int charsToCopy = current - from;
memcpy(to, from, (size_t)charsToCopy);
to += charsToCopy;
from = current+1;
current = strchr(from, '\r');
}
size_t remaining = strlen(from);
memcpy(to, from, remaining);
to += remaining;
*to = 0;
}
XClientMessageEvent m; XClientMessageEvent m;
memset(&m, sizeof(m), 0); memset(&m, sizeof(m), 0);
@ -792,7 +807,7 @@ static void processEvent(XEvent *event)
m.message_type = _glfw.x11.XdndFinished; m.message_type = _glfw.x11.XdndFinished;
m.format=32; m.format=32;
m.data.l[0] = window->x11.handle; m.data.l[0] = window->x11.handle;
m.data.l[1] = 1; m.data.l[1] = result;
m.data.l[2] = _glfw.x11.XdndActionCopy; //We only ever copy. m.data.l[2] = _glfw.x11.XdndActionCopy; //We only ever copy.
// Reply that all is well. // Reply that all is well.
@ -802,7 +817,7 @@ static void processEvent(XEvent *event)
XFree(data); XFree(data);
_glfwInputDrop(window,_glfw.x11.xdnd.string); if(result) _glfwInputDrop(window,_glfw.x11.xdnd.string);
} }
break; break;
} }
@ -1093,14 +1108,21 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
{ {
Window child; Window child;
int x, y; int x, y;
int left;
int top;
XTranslateCoordinates(_glfw.x11.display, window->x11.handle, _glfw.x11.root,
XTranslateCoordinates(_glfw.x11.display, window->x11.handle, _glfw.x11.root,
0, 0, &x, &y, &child); 0, 0, &x, &y, &child);
XTranslateCoordinates(_glfw.x11.display, window->x11.handle, child,
0, 0, &left, &top, &child);
if (xpos) if (xpos)
*xpos = x; *xpos = x;
if (ypos) if (ypos)
*ypos = y; *ypos = y-top;
} }
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos) void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)