mirror of
https://github.com/glfw/glfw.git
synced 2025-06-15 20:22:15 +00:00
Merge branch 'feature-dnd' of github.com:arturoc/glfw into feature-dnd
This commit is contained in:
commit
3ca9bb420a
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user