From cc9730d8a64966975bad0acfa26f1d8a1a97991c Mon Sep 17 00:00:00 2001 From: arturo Date: Wed, 10 Jul 2013 15:55:55 +0200 Subject: [PATCH 1/6] x11_window: use XTranslateCoordiantes to get correct coordiantes for XdndPosition --- src/x11_window.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/x11_window.c b/src/x11_window.c index 73cc8609..247d2c18 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -740,12 +740,14 @@ static void processEvent(XEvent *event) // and update the mouse position int absX = (event->xclient.data.l[2]>>16) & 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 XClientMessageEvent m; @@ -1093,14 +1095,21 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) { Window child; 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); + XTranslateCoordinates(_glfw.x11.display, window->x11.handle, child, + 0, 0, &left, &top, &child); + + if (xpos) *xpos = x; if (ypos) - *ypos = y; + *ypos = y-top; } void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos) From a978ed87b6dc026e2b13c44e602a62cc848dac50 Mon Sep 17 00:00:00 2001 From: arturo Date: Wed, 10 Jul 2013 16:37:01 +0200 Subject: [PATCH 2/6] cocoa_window.m: d&d implementation from theo, not working yet --- src/cocoa_window.m | 120 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 6209d1eb..e09b7c07 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -619,6 +619,126 @@ static int translateKey(unsigned int key) [self addCursorRect:[self bounds] cursor:_glfw.ns.cursor]; } +- (NSDragOperation)draggingEntered:(id )sender +{ + if ((NSDragOperationGeneric & [sender draggingSourceOperationMask]) + == NSDragOperationGeneric) { + + return NSDragOperationGeneric; + + } // end if + + // not a drag we can use + return NSDragOperationNone; + +} // end draggingEntered + +- (BOOL)prepareForDragOperation:(id )sender { + return YES; +} // end prepareForDragOperation + + + + +- (BOOL)performDragOperation:(id )sender { + + //int i; + int count; + NSPasteboard *zPasteboard = [sender draggingPasteboard]; + NSArray *files = [zPasteboard propertyListForType:NSFilenamesPboardType]; + + // define the images types we accept + // NSPasteboardTypeTIFF: (used to be NSTIFFPboardType). + // NSFilenamesPboardType:An array of NSString filenames + + //memset(fileNames, 0, 100*1000); + + int dragX = [sender draggingLocation].x; + int dragY = [sender draggingLocation].y; + + count = 0; + int howManyFiles = 0; + if ([files count]) { + NSEnumerator *filenameEnum = [files objectEnumerator]; + NSString *name; + while (name = [filenameEnum nextObject]) { + if (count < 100){ + if (strlen([name UTF8String]) < MAXPATHLEN){ + strcpy(fileNames[count], [name UTF8String]); + howManyFiles = count + 1; + //memcpy(fileNames[0], "hello", 5); + count++; + } + } + + } + } + + //memset(fileNames[0], 0, 100); + + + if(_dragEventFunc) { + (*_dragEventFunc)(fileNames, howManyFiles, dragX, dragY); + } + + + + + + //NSLog(@"Got a drag!"); + return YES; + /* + NSArray *zImageTypesAry = [NSArray arrayWithObjects:NSPasteboardTypeTIFF, + NSFilenamesPboardType, nil]; + + NSString *zDesiredType = [zPasteboard availableTypeFromArray:zImageTypesAry]; + + if ([zDesiredType isEqualToString:NSPasteboardTypeTIFF]) { + NSData *zPasteboardData = [zPasteboard dataForType:zDesiredType]; + if (zPasteboardData == nil) { + NSLog(@"Error: MyNSView performDragOperation zPasteboardData == nil"); + return NO; + } // end if + + self.nsImageObj = [[NSImage alloc] initWithData:zPasteboardData]; + [self setNeedsDisplay:YES]; + return YES; + + } //end if + + + if ([zDesiredType isEqualToString:NSFilenamesPboardType]) { + // the pasteboard contains a list of file names + //Take the first one + NSArray *zFileNamesAry = [zPasteboard propertyListForType:@"NSFilenamesPboardType"]; + NSString *zPath = [zFileNamesAry objectAtIndex:0]; + //NSImage *zNewImage = [[NSImage alloc] initWithContentsOfFile:zPath]; + + //if (zNewImage == nil) { + // NSLog(@"Error: MyNSView performDragOperation zNewImage == nil"); + // return NO; + // }// end if + // + // self.nsImageObj = zNewImage; + // [self setNeedsDisplay:YES]; + // + + NSLog(@"Got a drag!"); + return YES; + + }// end if + */ + //this can't happen ??? + //NSLog(@"Error MyNSView performDragOperation"); + //return NO; + +} // end performDragOperation + + +- (void)concludeDragOperation:(id )sender { + //[self setNeedsDisplay:YES]; +} // end concludeDragOperation + @end From 7aed0ad35ca231b645bd7a8cff0101d65bb06376 Mon Sep 17 00:00:00 2001 From: arturo Date: Wed, 10 Jul 2013 18:13:22 +0200 Subject: [PATCH 3/6] cocoa_window.m: fix d&d, mouse is dissapearing when drop received --- src/cocoa_window.m | 73 +++++++++------------------------------------- 1 file changed, 13 insertions(+), 60 deletions(-) diff --git a/src/cocoa_window.m b/src/cocoa_window.m index e09b7c07..29ae743d 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -422,6 +422,10 @@ static int translateKey(unsigned int key) trackingArea = nil; [self updateTrackingAreas]; + + + [self registerForDraggedTypes:[NSArray arrayWithObjects:NSTIFFPboardType, + NSFilenamesPboardType, nil]]; } return self; @@ -634,6 +638,7 @@ static int translateKey(unsigned int key) } // end draggingEntered - (BOOL)prepareForDragOperation:(id )sender { + [self setNeedsDisplay:YES]; return YES; } // end prepareForDragOperation @@ -651,22 +656,21 @@ static int translateKey(unsigned int key) // NSPasteboardTypeTIFF: (used to be NSTIFFPboardType). // NSFilenamesPboardType:An array of NSString filenames - //memset(fileNames, 0, 100*1000); + char fileNames[100*1000]; + memset(fileNames, 0, 100*1000); int dragX = [sender draggingLocation].x; int dragY = [sender draggingLocation].y; count = 0; - int howManyFiles = 0; if ([files count]) { NSEnumerator *filenameEnum = [files objectEnumerator]; NSString *name; while (name = [filenameEnum nextObject]) { if (count < 100){ if (strlen([name UTF8String]) < MAXPATHLEN){ - strcpy(fileNames[count], [name UTF8String]); - howManyFiles = count + 1; - //memcpy(fileNames[0], "hello", 5); + strcat(fileNames, [name UTF8String]); + strcat(fileNames, "\n"); count++; } } @@ -674,69 +678,18 @@ static int translateKey(unsigned int key) } } - //memset(fileNames[0], 0, 100); - - - if(_dragEventFunc) { - (*_dragEventFunc)(fileNames, howManyFiles, dragX, dragY); - } - - - - + int height; + _glfwPlatformGetWindowSize(window, NULL, &height); + _glfwInputCursorMotion(window, dragX, height-dragY); + _glfwInputDrop(window, fileNames); //NSLog(@"Got a drag!"); return YES; - /* - NSArray *zImageTypesAry = [NSArray arrayWithObjects:NSPasteboardTypeTIFF, - NSFilenamesPboardType, nil]; - - NSString *zDesiredType = [zPasteboard availableTypeFromArray:zImageTypesAry]; - - if ([zDesiredType isEqualToString:NSPasteboardTypeTIFF]) { - NSData *zPasteboardData = [zPasteboard dataForType:zDesiredType]; - if (zPasteboardData == nil) { - NSLog(@"Error: MyNSView performDragOperation zPasteboardData == nil"); - return NO; - } // end if - - self.nsImageObj = [[NSImage alloc] initWithData:zPasteboardData]; - [self setNeedsDisplay:YES]; - return YES; - - } //end if - - - if ([zDesiredType isEqualToString:NSFilenamesPboardType]) { - // the pasteboard contains a list of file names - //Take the first one - NSArray *zFileNamesAry = [zPasteboard propertyListForType:@"NSFilenamesPboardType"]; - NSString *zPath = [zFileNamesAry objectAtIndex:0]; - //NSImage *zNewImage = [[NSImage alloc] initWithContentsOfFile:zPath]; - - //if (zNewImage == nil) { - // NSLog(@"Error: MyNSView performDragOperation zNewImage == nil"); - // return NO; - // }// end if - // - // self.nsImageObj = zNewImage; - // [self setNeedsDisplay:YES]; - // - - NSLog(@"Got a drag!"); - return YES; - - }// end if - */ - //this can't happen ??? - //NSLog(@"Error MyNSView performDragOperation"); - //return NO; } // end performDragOperation - (void)concludeDragOperation:(id )sender { - //[self setNeedsDisplay:YES]; } // end concludeDragOperation @end From 9e9e75f3314426b47bc77cbaa0cdac75565a74e1 Mon Sep 17 00:00:00 2001 From: arturo Date: Thu, 11 Jul 2013 22:50:46 +0200 Subject: [PATCH 4/6] cocoa_window: fix mouse dissapearing after drop and on resize --- src/cocoa_window.m | 75 ++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 29ae743d..3925b107 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -390,6 +390,8 @@ static int translateKey(unsigned int key) @interface GLFWContentView : NSView { _GLFWwindow* window; + char * fileNamesForDrag; + int fileNamesSize; NSTrackingArea* trackingArea; } @@ -420,11 +422,14 @@ static int translateKey(unsigned int key) { window = initWindow; trackingArea = nil; - + + fileNamesForDrag = (char*)malloc(1024); + fileNamesSize = 1024; + [self updateTrackingAreas]; - [self registerForDraggedTypes:[NSArray arrayWithObjects:NSTIFFPboardType, + [self registerForDraggedTypes:[NSArray arrayWithObjects: NSFilenamesPboardType, nil]]; } @@ -434,6 +439,7 @@ static int translateKey(unsigned int key) -(void)dealloc { [trackingArea release]; + free(fileNamesForDrag); [super dealloc]; } @@ -617,80 +623,71 @@ static int translateKey(unsigned int key) _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 addCursorRect:[self bounds] cursor:_glfw.ns.cursor]; -} +}*/ - (NSDragOperation)draggingEntered:(id )sender { if ((NSDragOperationGeneric & [sender draggingSourceOperationMask]) == NSDragOperationGeneric) { - + + [self setNeedsDisplay:YES]; + return NSDragOperationGeneric; - } // end if - - // not a drag we can use + } + return NSDragOperationNone; - -} // end draggingEntered +} - (BOOL)prepareForDragOperation:(id )sender { [self setNeedsDisplay:YES]; return YES; -} // end prepareForDragOperation - - - +} - (BOOL)performDragOperation:(id )sender { - - //int i; - int count; NSPasteboard *zPasteboard = [sender draggingPasteboard]; NSArray *files = [zPasteboard propertyListForType:NSFilenamesPboardType]; - - // define the images types we accept - // NSPasteboardTypeTIFF: (used to be NSTIFFPboardType). - // NSFilenamesPboardType:An array of NSString filenames - char fileNames[100*1000]; - memset(fileNames, 0, 100*1000); + // 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; - count = 0; + int dragSize = 1; if ([files count]) { NSEnumerator *filenameEnum = [files objectEnumerator]; NSString *name; while (name = [filenameEnum nextObject]) { - if (count < 100){ - if (strlen([name UTF8String]) < MAXPATHLEN){ - strcat(fileNames, [name UTF8String]); - strcat(fileNames, "\n"); - count++; - } - } - + 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, fileNames); - - //NSLog(@"Got a drag!"); + _glfwInputDrop(window, fileNamesForDrag); + return YES; - -} // end performDragOperation - +} - (void)concludeDragOperation:(id )sender { -} // end concludeDragOperation + [self setNeedsDisplay:YES]; +} @end From 0322154670e7537dda10e7b87fb29af76cc8382c Mon Sep 17 00:00:00 2001 From: arturo Date: Fri, 12 Jul 2013 01:29:25 +0200 Subject: [PATCH 5/6] x11: fix d&d type conversions + remove \r in paths --- src/x11_init.c | 3 --- src/x11_platform.h | 3 --- src/x11_window.c | 58 ++++++++++++++++++++++++++++++---------------- 3 files changed, 38 insertions(+), 26 deletions(-) diff --git a/src/x11_init.c b/src/x11_init.c index eed9f5a2..cd3f5bfd 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -546,14 +546,11 @@ static GLboolean initExtensions(void) _glfw.x11.XdndEnter = XInternAtom(_glfw.x11.display, "XdndEnter", False); _glfw.x11.XdndPosition = XInternAtom(_glfw.x11.display, "XdndPosition", 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.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", False); _glfw.x11.XdndLeave = XInternAtom(_glfw.x11.display, "XdndLeave", False); _glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", 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.type1 = NULL; _glfw.x11.xdnd.type2 = NULL; diff --git a/src/x11_platform.h b/src/x11_platform.h index 71a0febc..70a9d5d1 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -127,14 +127,11 @@ typedef struct _GLFWlibraryX11 Atom XdndEnter; Atom XdndPosition; Atom XdndStatus; - Atom XdndTypeList; Atom XdndActionCopy; Atom XdndDrop; Atom XdndLeave; Atom XdndFinished; Atom XdndSelection; - Atom XdndProxy; - Atom XA_TARGETS; struct{ Window sourceWindow; char* string; diff --git a/src/x11_window.c b/src/x11_window.c index 247d2c18..c2aa7b69 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -701,6 +701,11 @@ static void processEvent(XEvent *event) event); } + +#define xdndEnter_sourceWindow(evt) ( (evt)->data.l[0]) +#define xdndEnter_version(evt) ( (evt)->data.l[1] >> 24) +#define xdndEnter_hasThreeTypes(evt) (((evt)->xclient.data.l[1] & 0x1UL) == 0) +#define xdndEnter_typeAt(evt, idx) ( (evt)->xclient.data.l[2 + (idx)]) else if(event->xclient.message_type == _glfw.x11.XdndEnter) { // Xdnd Enter: the drag&drop event has started in the window, @@ -714,20 +719,11 @@ static void processEvent(XEvent *event) // the window, ask to convert the selection _glfw.x11.xdnd.sourceWindow = event->xclient.data.l[0]; - - const Atom formats[] = { _glfw.x11.UTF8_STRING, - _glfw.x11.COMPOUND_STRING, - XA_STRING }; - const int formatCount = sizeof(formats) / sizeof(formats[0]); - int i; - - for(i=0;ix11.handle, CurrentTime); - } + XConvertSelection(_glfw.x11.display, + _glfw.x11.XdndSelection, + _glfw.x11.UTF8_STRING, + _glfw.x11.XdndSelection, + window->x11.handle, CurrentTime); } else if(event->xclient.message_type == _glfw.x11.XdndLeave) @@ -765,7 +761,6 @@ static void processEvent(XEvent *event) XSendEvent(_glfw.x11.display, event->xclient.data.l[0], False, NoEventMask, (XEvent*)&m); XFlush(_glfw.x11.display); - } break; @@ -778,13 +773,36 @@ static void processEvent(XEvent *event) // Xdnd: got a selection notification from the conversion // we asked for, get the data and finish the d&d event 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.target, (unsigned char**) &data); - free(_glfw.x11.xdnd.string); - _glfw.x11.xdnd.string = strdup(data); + if(result){ + // 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; memset(&m, sizeof(m), 0); @@ -794,7 +812,7 @@ static void processEvent(XEvent *event) m.message_type = _glfw.x11.XdndFinished; m.format=32; 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. // Reply that all is well. @@ -804,7 +822,7 @@ static void processEvent(XEvent *event) XFree(data); - _glfwInputDrop(window,_glfw.x11.xdnd.string); + if(result) _glfwInputDrop(window,_glfw.x11.xdnd.string); } break; } From f821439de618797fa36310733b9fd43e4afad7cb Mon Sep 17 00:00:00 2001 From: arturo Date: Fri, 12 Jul 2013 01:30:32 +0200 Subject: [PATCH 6/6] x11_window: remove debug code --- src/x11_window.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/x11_window.c b/src/x11_window.c index c2aa7b69..4e30476e 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -701,11 +701,6 @@ static void processEvent(XEvent *event) event); } - -#define xdndEnter_sourceWindow(evt) ( (evt)->data.l[0]) -#define xdndEnter_version(evt) ( (evt)->data.l[1] >> 24) -#define xdndEnter_hasThreeTypes(evt) (((evt)->xclient.data.l[1] & 0x1UL) == 0) -#define xdndEnter_typeAt(evt, idx) ( (evt)->xclient.data.l[2 + (idx)]) else if(event->xclient.message_type == _glfw.x11.XdndEnter) { // Xdnd Enter: the drag&drop event has started in the window,