This commit is contained in:
Camilla Berglund 2013-12-22 16:38:56 +01:00
parent 89d0723ba3
commit 8ae063bb1b
7 changed files with 203 additions and 201 deletions

View File

@ -445,13 +445,11 @@ static int translateKey(unsigned int key)
{ {
window = initWindow; window = initWindow;
trackingArea = nil; trackingArea = nil;
fileNamesForDrag = (char*)malloc(1024); fileNamesForDrag = malloc(1024);
fileNamesSize = 1024; fileNamesSize = 1024;
[self updateTrackingAreas]; [self updateTrackingAreas];
[self registerForDraggedTypes:[NSArray arrayWithObjects: [self registerForDraggedTypes:[NSArray arrayWithObjects:
NSFilenamesPboardType, nil]]; NSFilenamesPboardType, nil]];
} }
@ -667,69 +665,75 @@ 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
{ {
// This makes the cursor dissapear when the window is
// resized or received a drag operation
[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 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{ {
if ((NSDragOperationGeneric & [sender draggingSourceOperationMask]) if ((NSDragOperationGeneric & [sender draggingSourceOperationMask])
== NSDragOperationGeneric) { == NSDragOperationGeneric)
{
[self setNeedsDisplay:YES]; [self setNeedsDisplay:YES];
return NSDragOperationGeneric; return NSDragOperationGeneric;
} }
return NSDragOperationNone; return NSDragOperationNone;
} }
- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender { - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
{
[self setNeedsDisplay:YES]; [self setNeedsDisplay:YES];
return YES; return YES;
} }
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender { - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
NSPasteboard *zPasteboard = [sender draggingPasteboard]; {
NSArray *files = [zPasteboard propertyListForType:NSFilenamesPboardType]; NSPasteboard* pasteboard = [sender draggingPasteboard];
NSArray* files = [pasteboard propertyListForType:NSFilenamesPboardType];
// set the first char to 0 so strcat // set the first char to 0 so strcat
// starts to add from the beginning // starts to add from the beginning
fileNamesForDrag[0] = 0; fileNamesForDrag[0] = 0;
int dragX = [sender draggingLocation].x; const int dragX = [sender draggingLocation].x;
int dragY = [sender draggingLocation].y; const int dragY = [sender draggingLocation].y;
int dragSize = 1;
int dragSize = 1;
if ([files count]) { if ([files count])
NSEnumerator *filenameEnum = [files objectEnumerator]; {
NSString *name; NSEnumerator* filenameEnum = [files objectEnumerator];
while (name = [filenameEnum nextObject]) { NSString* name;
dragSize += [name length]+1;
if (dragSize > fileNamesSize){ while (name = [filenameEnum nextObject])
{
dragSize += [name length] + 1;
if (dragSize > fileNamesSize)
{
fileNamesSize *= 2; fileNamesSize *= 2;
fileNamesForDrag = realloc(fileNamesForDrag, fileNamesSize); fileNamesForDrag = realloc(fileNamesForDrag, fileNamesSize);
} }
strcat(fileNamesForDrag, [name UTF8String]); strcat(fileNamesForDrag, [name UTF8String]);
strcat(fileNamesForDrag, "\n"); strcat(fileNamesForDrag, "\n");
} }
} }
int height; int height;
_glfwPlatformGetWindowSize(window, NULL, &height); _glfwPlatformGetWindowSize(window, NULL, &height);
_glfwInputCursorMotion(window, dragX, height-dragY); _glfwInputCursorMotion(window, dragX, height - dragY);
_glfwInputDrop(window, fileNamesForDrag); _glfwInputDrop(window, fileNamesForDrag);
return YES; return YES;
} }
- (void)concludeDragOperation:(id <NSDraggingInfo>)sender { - (void)concludeDragOperation:(id <NSDraggingInfo>)sender
{
[self setNeedsDisplay:YES]; [self setNeedsDisplay:YES];
} }

View File

@ -211,8 +211,8 @@ void _glfwInputCursorEnter(_GLFWwindow* window, int entered)
window->callbacks.cursorEnter((GLFWwindow*) window, entered); window->callbacks.cursorEnter((GLFWwindow*) window, entered);
} }
void _glfwInputDrop(_GLFWwindow* window, const char* dropString){ void _glfwInputDrop(_GLFWwindow* window, const char* dropString)
{
if (window->callbacks.drop) if (window->callbacks.drop)
window->callbacks.drop((GLFWwindow*) window, dropString); window->callbacks.drop((GLFWwindow*) window, dropString);
} }
@ -403,11 +403,8 @@ GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* handle,
GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun) GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
GLFWdropfun previous;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(window->callbacks.drop, cbfun);
previous = window->callbacks.drop; return cbfun;
window->callbacks.drop = cbfun;
return previous;
} }

View File

@ -98,7 +98,7 @@ static GLboolean initLibraries(void)
_glfw.win32.dwmapi.DwmIsCompositionEnabled = (DWMISCOMPOSITIONENABLED_T) _glfw.win32.dwmapi.DwmIsCompositionEnabled = (DWMISCOMPOSITIONENABLED_T)
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled"); GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
} }
return GL_TRUE; return GL_TRUE;
} }
@ -214,8 +214,8 @@ int _glfwPlatformInit(void)
if (!_glfwInitContextAPI()) if (!_glfwInitContextAPI())
return GL_FALSE; return GL_FALSE;
_glfw.win32.dropString = (char*)malloc(1000); _glfw.win32.dropString = malloc(1000);
_glfw.win32.dropStringSize = 1000; _glfw.win32.dropStringSize = 1000;
_glfwInitTimer(); _glfwInitTimer();

View File

@ -749,38 +749,43 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
// TODO: Restore vsync if compositing was disabled // TODO: Restore vsync if compositing was disabled
break; break;
} }
case WM_DROPFILES: case WM_DROPFILES:
{ {
TCHAR szName[MAX_PATH]; WCHAR szName[MAX_PATH];
HDROP hDrop = (HDROP)wParam; HDROP hDrop = (HDROP) wParam;
POINT pt; POINT pt;
int numFiles = DragQueryFile(hDrop, 0xFFFFFFFF, szName, MAX_PATH); const int numFiles = DragQueryFile(hDrop, 0xffffffff, szName, MAX_PATH);
int currentSize = 1; int i, currentSize = 1;
int i; char* utf8str;
char* utf8str;
DragQueryPoint(hDrop, &pt);
// Move the mouse to the position of the drop // Move the mouse to the position of the drop
_glfwInputCursorMotion(window,pt.x,pt.y); DragQueryPoint(hDrop, &pt);
_glfwInputCursorMotion(window, pt.x, pt.y);
memset(_glfw.win32.dropString, 0, _glfw.win32.dropStringSize);
for(i = 0; i < numFiles; i++) memset(_glfw.win32.dropString, 0, _glfw.win32.dropStringSize);
{
DragQueryFile(hDrop, i, szName, MAX_PATH); for (i = 0; i < numFiles; i++)
utf8str = _glfwCreateUTF8FromWideString((const wchar_t*)szName); {
currentSize += strlen(utf8str); DragQueryFile(hDrop, i, szName, MAX_PATH);
if(_glfw.win32.dropStringSize < currentSize){ utf8str = _glfwCreateUTF8FromWideString((const WCHAR*) szName);
_glfw.win32.dropStringSize *= 2; currentSize += strlen(utf8str);
_glfw.win32.dropString = (char*)realloc(_glfw.win32.dropString,_glfw.win32.dropStringSize);
} if (_glfw.win32.dropStringSize < currentSize)
strcat(_glfw.win32.dropString, utf8str); {
strcat(_glfw.win32.dropString, "\n"); _glfw.win32.dropStringSize *= 2;
free(utf8str); _glfw.win32.dropString = realloc(_glfw.win32.dropString,
} _glfw.win32.dropStringSize);
}
_glfwInputDrop(window,_glfw.win32.dropString);
DragFinish(hDrop); strcat(_glfw.win32.dropString, utf8str);
break; strcat(_glfw.win32.dropString, "\n");
free(utf8str);
}
_glfwInputDrop(window,_glfw.win32.dropString);
DragFinish(hDrop);
break;
} }
} }
@ -900,8 +905,8 @@ static int createWindow(_GLFWwindow* window,
window); // Pass object to WM_CREATE window); // Pass object to WM_CREATE
free(wideTitle); free(wideTitle);
DragAcceptFiles(window->win32.handle, TRUE); DragAcceptFiles(window->win32.handle, TRUE);
if (!window->win32.handle) if (!window->win32.handle)
{ {

View File

@ -540,8 +540,6 @@ static GLboolean initExtensions(void)
XInternAtom(_glfw.x11.display, "SAVE_TARGETS", False); XInternAtom(_glfw.x11.display, "SAVE_TARGETS", False);
// Find or create drag and drop atoms // Find or create drag and drop atoms
//Atoms for Xdnd
_glfw.x11.XdndAware = XInternAtom(_glfw.x11.display, "XdndAware", True); _glfw.x11.XdndAware = XInternAtom(_glfw.x11.display, "XdndAware", True);
_glfw.x11.XdndEnter = XInternAtom(_glfw.x11.display, "XdndEnter", True); _glfw.x11.XdndEnter = XInternAtom(_glfw.x11.display, "XdndEnter", True);
_glfw.x11.XdndPosition = XInternAtom(_glfw.x11.display, "XdndPosition", True); _glfw.x11.XdndPosition = XInternAtom(_glfw.x11.display, "XdndPosition", True);
@ -552,8 +550,6 @@ static GLboolean initExtensions(void)
_glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", True); _glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", True);
_glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", True); _glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", True);
return GL_TRUE; return GL_TRUE;
} }

View File

@ -121,20 +121,21 @@ typedef struct _GLFWlibraryX11
// Atoms for Xdnd // Atoms for Xdnd
Atom XdndAware; Atom XdndAware;
Atom XdndEnter; Atom XdndEnter;
Atom XdndPosition; Atom XdndPosition;
Atom XdndStatus; Atom XdndStatus;
Atom XdndActionCopy; Atom XdndActionCopy;
Atom XdndDrop; Atom XdndDrop;
Atom XdndLeave; Atom XdndLeave;
Atom XdndFinished; Atom XdndFinished;
Atom XdndSelection; Atom XdndSelection;
struct{
Window sourceWindow; struct {
char* string; Window sourceWindow;
char* type1; char* string;
char* type2; char* type1;
char* type3; char* type2;
char* type3;
} xdnd; } xdnd;
// Selection atoms // Selection atoms

View File

@ -306,12 +306,14 @@ static GLboolean createWindow(_GLFWwindow* window,
XISelectEvents(_glfw.x11.display, window->x11.handle, &eventmask, 1); XISelectEvents(_glfw.x11.display, window->x11.handle, &eventmask, 1);
} }
// Enable Xdnd if (_glfw.x11.XdndAware)
if(_glfw.x11.XdndAware!=None)
{ {
//Announce XDND support // Announce support for XDND version 5 and below
Atom version=5;
XChangeProperty(_glfw.x11.display, window->x11.handle, _glfw.x11.XdndAware, XA_ATOM, 32, PropModeReplace, (unsigned char*)&version, 1); const Atom version = 5;
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.XdndAware, XA_ATOM, 32,
PropModeReplace, (unsigned char*) &version, 1);
} }
_glfwPlatformSetWindowTitle(window, wndconfig->title); _glfwPlatformSetWindowTitle(window, wndconfig->title);
@ -714,126 +716,123 @@ static void processEvent(XEvent *event)
event); event);
} }
else if(event->xclient.message_type == _glfw.x11.XdndEnter) else if (event->xclient.message_type == _glfw.x11.XdndEnter)
{ {
// Xdnd Enter: the drag&drop event has started in the window, // Xdnd Enter: the drag&drop event has started in the window, we
// we could be getting the type and possible conversions here // could be getting the type and possible conversions here but
// but since we use always string conversion we don't need // since we use always string conversion we don't need it
// it
} }
else if(event->xclient.message_type == _glfw.x11.XdndDrop) else if (event->xclient.message_type == _glfw.x11.XdndDrop)
{ {
// Xdnd Drop: The drag&drop event has finished dropping on // Xdnd Drop: The drag&drop event has finished dropping on
// 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, XConvertSelection(_glfw.x11.display,
_glfw.x11.XdndSelection, _glfw.x11.XdndSelection,
_glfw.x11.UTF8_STRING, _glfw.x11.UTF8_STRING,
_glfw.x11.XdndSelection, _glfw.x11.XdndSelection,
window->x11.handle, CurrentTime); window->x11.handle, CurrentTime);
} }
else if(event->xclient.message_type == _glfw.x11.XdndLeave) else if (event->xclient.message_type == _glfw.x11.XdndLeave)
{ {
} }
else if(event->xclient.message_type == _glfw.x11.XdndPosition) else if (event->xclient.message_type == _glfw.x11.XdndPosition)
{ {
// Xdnd Position: get coordinates of the mouse inside the window // Xdnd Position: get coordinates of the mouse inside the window
// and update the mouse position // and update the mouse position
int absX = (event->xclient.data.l[2]>>16) & 0xFFFF; const int absX = (event->xclient.data.l[2] >> 16) & 0xFFFF;
int absY = (event->xclient.data.l[2]) & 0xFFFF; const int absY = (event->xclient.data.l[2]) & 0xFFFF;
int x; int x, y;
int y;
_glfwPlatformGetWindowPos(window,&x,&y); _glfwPlatformGetWindowPos(window, &x, &y);
_glfwInputCursorMotion(window, absX - x, absY - y);
_glfwInputCursorMotion(window,absX-x,absY-y); // Xdnd: reply with an XDND status message
XEvent reply;
memset(&reply, sizeof(reply), 0);
// Xdnd: reply with an XDND status message reply.type = ClientMessage;
XClientMessageEvent m; reply.xclient.window = event->xclient.data.l[0];
memset(&m, sizeof(m), 0); reply.xclient.message_type = _glfw.x11.XdndStatus;
m.type = ClientMessage; reply.xclient.format = 32;
m.display = event->xclient.display; reply.xclient.data.l[0] = window->x11.handle;
m.window = event->xclient.data.l[0]; reply.xclient.data.l[1] = 1; // Always accept the dnd with no rectangle
m.message_type = _glfw.x11.XdndStatus; reply.xclient.data.l[2] = 0; // Specify an empty rectangle
m.format=32; reply.xclient.data.l[3] = 0;
m.data.l[0] = window->x11.handle; reply.xclient.data.l[4] = _glfw.x11.XdndActionCopy; // We only accept copying
m.data.l[1] = 1; // Always accept the dnd with no rectangle
m.data.l[2] = 0; // Specify an empty rectangle
m.data.l[3] = 0;
m.data.l[4] = _glfw.x11.XdndActionCopy; // We only accept copying
XSendEvent(_glfw.x11.display, event->xclient.data.l[0], False, NoEventMask, (XEvent*)&m); XSendEvent(_glfw.x11.display, window->x11.handle,
XFlush(_glfw.x11.display); False, NoEventMask, &reply);
XFlush(_glfw.x11.display);
} }
break; break;
} }
case SelectionNotify: case SelectionNotify:
{ {
if(event->xselection.property != None) if (event->xselection.property != None)
{ {
// 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;
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);
if(result){ free(_glfw.x11.xdnd.string);
// nautilus seems to add a \r at the end of the paths _glfw.x11.xdnd.string = NULL;
// 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; const int result = _glfwGetWindowProperty(event->xselection.requestor,
current = strchr(from, '\r'); event->xselection.property,
} event->xselection.target,
(unsigned char**) &data);
size_t remaining = strlen(from); 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');
memcpy(to, from, remaining); while (current)
to += remaining; {
*to = 0; const int charsToCopy = current - from;
} memcpy(to, from, (size_t) charsToCopy);
to += charsToCopy;
XClientMessageEvent m; from = current + 1;
memset(&m, sizeof(m), 0); current = strchr(from, '\r');
m.type = ClientMessage; }
m.display = _glfw.x11.display;
m.window = _glfw.x11.xdnd.sourceWindow;
m.message_type = _glfw.x11.XdndFinished;
m.format=32;
m.data.l[0] = window->x11.handle;
m.data.l[1] = result;
m.data.l[2] = _glfw.x11.XdndActionCopy; //We only ever copy.
// Reply that all is well. const size_t remaining = strlen(from);
XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.sourceWindow, False, NoEventMask, (XEvent*)&m);
XSync(_glfw.x11.display, False); memcpy(to, from, remaining);
to += remaining;
*to = 0;
}
XFree(data); XEvent reply;
memset(&reply, sizeof(reply), 0);
reply.type = ClientMessage;
reply.xclient.window = _glfw.x11.xdnd.sourceWindow;
reply.xclient.message_type = _glfw.x11.XdndFinished;
reply.xclient.format = 32;
reply.xclient.data.l[0] = window->x11.handle;
reply.xclient.data.l[1] = result;
reply.xclient.data.l[2] = _glfw.x11.XdndActionCopy; // We only ever copy
if(result) // Reply that all is well
{ XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.sourceWindow,
_glfwInputDrop(window,_glfw.x11.xdnd.string); False, NoEventMask, &reply);
XSync(_glfw.x11.display, False);
XFree(data);
} if (result)
} _glfwInputDrop(window, _glfw.x11.xdnd.string);
break; }
}
break;
}
case MapNotify: case MapNotify:
{ {