|
|
|
@ -306,6 +306,14 @@ static GLboolean createWindow(_GLFWwindow* window, |
|
|
|
|
XISelectEvents(_glfw.x11.display, window->x11.handle, &eventmask, 1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Enable Xdnd
|
|
|
|
|
if(_glfw.x11.XdndAware!=None) |
|
|
|
|
{ |
|
|
|
|
//Announce XDND support
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
XRRSelectInput(_glfw.x11.display, window->x11.handle, |
|
|
|
@ -494,6 +502,7 @@ static void leaveFullscreenMode(_GLFWwindow* window) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Process the specified X event
|
|
|
|
|
//
|
|
|
|
|
static void processEvent(XEvent *event) |
|
|
|
@ -703,10 +712,128 @@ static void processEvent(XEvent *event) |
|
|
|
|
False, |
|
|
|
|
SubstructureNotifyMask | SubstructureRedirectMask, |
|
|
|
|
event); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
else if(event->xclient.message_type == _glfw.x11.XdndEnter) |
|
|
|
|
{ |
|
|
|
|
// Xdnd Enter: the drag&drop event has started in the window,
|
|
|
|
|
// we could be getting the type and possible conversions here
|
|
|
|
|
// but since we use always string conversion we don't need
|
|
|
|
|
// it
|
|
|
|
|
} |
|
|
|
|
else if(event->xclient.message_type == _glfw.x11.XdndDrop) |
|
|
|
|
{ |
|
|
|
|
// Xdnd Drop: The drag&drop event has finished dropping on
|
|
|
|
|
// the window, ask to convert the selection
|
|
|
|
|
_glfw.x11.xdnd.sourceWindow = event->xclient.data.l[0]; |
|
|
|
|
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) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
else if(event->xclient.message_type == _glfw.x11.XdndPosition) |
|
|
|
|
{ |
|
|
|
|
// Xdnd Position: get coordinates of the mouse inside the window
|
|
|
|
|
// 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); |
|
|
|
|
|
|
|
|
|
_glfwInputCursorMotion(window,absX-x,absY-y); |
|
|
|
|
|
|
|
|
|
// Xdnd: reply with an XDND status message
|
|
|
|
|
XClientMessageEvent m; |
|
|
|
|
memset(&m, sizeof(m), 0); |
|
|
|
|
m.type = ClientMessage; |
|
|
|
|
m.display = event->xclient.display; |
|
|
|
|
m.window = event->xclient.data.l[0]; |
|
|
|
|
m.message_type = _glfw.x11.XdndStatus; |
|
|
|
|
m.format=32; |
|
|
|
|
m.data.l[0] = window->x11.handle; |
|
|
|
|
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); |
|
|
|
|
XFlush(_glfw.x11.display); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case SelectionNotify: |
|
|
|
|
{ |
|
|
|
|
if(event->xselection.property != None) |
|
|
|
|
{ |
|
|
|
|
// Xdnd: got a selection notification from the conversion
|
|
|
|
|
// we asked for, get the data and finish the d&d event
|
|
|
|
|
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){ |
|
|
|
|
// 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); |
|
|
|
|
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.
|
|
|
|
|
XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.sourceWindow, False, NoEventMask, (XEvent*)&m); |
|
|
|
|
|
|
|
|
|
XSync(_glfw.x11.display, False); |
|
|
|
|
|
|
|
|
|
XFree(data); |
|
|
|
|
|
|
|
|
|
if(result) |
|
|
|
|
{ |
|
|
|
|
_glfwInputDrop(window,_glfw.x11.xdnd.string); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case MapNotify: |
|
|
|
|
{ |
|
|
|
@ -897,7 +1024,7 @@ unsigned long _glfwGetWindowProperty(Window window, |
|
|
|
|
&bytesAfter, |
|
|
|
|
value); |
|
|
|
|
|
|
|
|
|
if (actualType != type) |
|
|
|
|
if (type != AnyPropertyType && actualType != type) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
return itemCount; |
|
|
|
@ -1001,7 +1128,6 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) |
|
|
|
|
if (child) |
|
|
|
|
{ |
|
|
|
|
int left, top; |
|
|
|
|
|
|
|
|
|
XTranslateCoordinates(_glfw.x11.display, window->x11.handle, child, |
|
|
|
|
0, 0, &left, &top, &child); |
|
|
|
|
|
|
|
|
|