mirror of
https://github.com/glfw/glfw.git
synced 2024-11-29 21:37:27 +00:00
X11: Implement extended drag & drop API
This commit is contained in:
parent
2933c00e54
commit
0a757737d3
@ -910,11 +910,6 @@ static GLFWbool initExtensions(void)
|
|||||||
// the keyboard mapping.
|
// the keyboard mapping.
|
||||||
createKeyTables();
|
createKeyTables();
|
||||||
|
|
||||||
// String format atoms
|
|
||||||
_glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False);
|
|
||||||
_glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False);
|
|
||||||
_glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False);
|
|
||||||
|
|
||||||
// Custom selection property atom
|
// Custom selection property atom
|
||||||
_glfw.x11.GLFW_SELECTION =
|
_glfw.x11.GLFW_SELECTION =
|
||||||
XInternAtom(_glfw.x11.display, "GLFW_SELECTION", False);
|
XInternAtom(_glfw.x11.display, "GLFW_SELECTION", False);
|
||||||
@ -925,6 +920,7 @@ static GLFWbool initExtensions(void)
|
|||||||
_glfw.x11.PRIMARY = XInternAtom(_glfw.x11.display, "PRIMARY", False);
|
_glfw.x11.PRIMARY = XInternAtom(_glfw.x11.display, "PRIMARY", False);
|
||||||
_glfw.x11.INCR = XInternAtom(_glfw.x11.display, "INCR", False);
|
_glfw.x11.INCR = XInternAtom(_glfw.x11.display, "INCR", False);
|
||||||
_glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False);
|
_glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False);
|
||||||
|
_glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False);
|
||||||
|
|
||||||
// Clipboard manager atoms
|
// Clipboard manager atoms
|
||||||
_glfw.x11.CLIPBOARD_MANAGER =
|
_glfw.x11.CLIPBOARD_MANAGER =
|
||||||
@ -937,11 +933,24 @@ static GLFWbool 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.XdndActionCopy = XInternAtom(_glfw.x11.display, "XdndActionCopy", False);
|
_glfw.x11.XdndLeave = XInternAtom(_glfw.x11.display, "XdndLeave", False);
|
||||||
|
_glfw.x11.XdndActions[_GLFW_DND_COPY_INDEX] =
|
||||||
|
XInternAtom(_glfw.x11.display, "XdndActionCopy", False);
|
||||||
|
_glfw.x11.XdndActions[_GLFW_DND_LINK_INDEX] =
|
||||||
|
XInternAtom(_glfw.x11.display, "XdndActionLink", False);
|
||||||
|
_glfw.x11.XdndActions[_GLFW_DND_MOVE_INDEX] =
|
||||||
|
XInternAtom(_glfw.x11.display, "XdndActionMove", False);
|
||||||
_glfw.x11.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", False);
|
_glfw.x11.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", 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.XdndTypeList = XInternAtom(_glfw.x11.display, "XdndTypeList", False);
|
_glfw.x11.XdndTypeList = XInternAtom(_glfw.x11.display, "XdndTypeList", False);
|
||||||
|
|
||||||
|
// Format atoms (shared by Xdnd and selection)
|
||||||
|
_glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False);
|
||||||
|
_glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False);
|
||||||
|
_glfw.x11.STRING = XInternAtom(_glfw.x11.display, "STRING", False);
|
||||||
|
_glfw.x11.TEXT = XInternAtom(_glfw.x11.display, "TEXT", False);
|
||||||
|
_glfw.x11.text_plain = XInternAtom(_glfw.x11.display, "text/plain", False);
|
||||||
_glfw.x11.text_uri_list = XInternAtom(_glfw.x11.display, "text/uri-list", False);
|
_glfw.x11.text_uri_list = XInternAtom(_glfw.x11.display, "text/uri-list", False);
|
||||||
|
|
||||||
// ICCCM, EWMH and Motif window property atoms
|
// ICCCM, EWMH and Motif window property atoms
|
||||||
|
@ -97,6 +97,9 @@ typedef struct __GLXFBConfig* GLXFBConfig;
|
|||||||
typedef struct __GLXcontext* GLXContext;
|
typedef struct __GLXcontext* GLXContext;
|
||||||
typedef void (*__GLXextproc)(void);
|
typedef void (*__GLXextproc)(void);
|
||||||
|
|
||||||
|
// TODO for dev; remove
|
||||||
|
typedef char* (* PFN_XGetAtomName)(Display*,Atom);
|
||||||
|
|
||||||
typedef XClassHint* (* PFN_XAllocClassHint)(void);
|
typedef XClassHint* (* PFN_XAllocClassHint)(void);
|
||||||
typedef XSizeHints* (* PFN_XAllocSizeHints)(void);
|
typedef XSizeHints* (* PFN_XAllocSizeHints)(void);
|
||||||
typedef XWMHints* (* PFN_XAllocWMHints)(void);
|
typedef XWMHints* (* PFN_XAllocWMHints)(void);
|
||||||
@ -622,12 +625,12 @@ typedef struct _GLFWlibraryX11
|
|||||||
Atom XdndEnter;
|
Atom XdndEnter;
|
||||||
Atom XdndPosition;
|
Atom XdndPosition;
|
||||||
Atom XdndStatus;
|
Atom XdndStatus;
|
||||||
Atom XdndActionCopy;
|
Atom XdndLeave;
|
||||||
|
Atom XdndActions[_GLFW_DND_ACTION_COUNT];
|
||||||
Atom XdndDrop;
|
Atom XdndDrop;
|
||||||
Atom XdndFinished;
|
Atom XdndFinished;
|
||||||
Atom XdndSelection;
|
Atom XdndSelection;
|
||||||
Atom XdndTypeList;
|
Atom XdndTypeList;
|
||||||
Atom text_uri_list;
|
|
||||||
|
|
||||||
// Selection (clipboard) atoms
|
// Selection (clipboard) atoms
|
||||||
Atom TARGETS;
|
Atom TARGETS;
|
||||||
@ -637,12 +640,17 @@ typedef struct _GLFWlibraryX11
|
|||||||
Atom PRIMARY;
|
Atom PRIMARY;
|
||||||
Atom CLIPBOARD_MANAGER;
|
Atom CLIPBOARD_MANAGER;
|
||||||
Atom SAVE_TARGETS;
|
Atom SAVE_TARGETS;
|
||||||
Atom NULL_;
|
|
||||||
Atom UTF8_STRING;
|
|
||||||
Atom COMPOUND_STRING;
|
|
||||||
Atom ATOM_PAIR;
|
Atom ATOM_PAIR;
|
||||||
Atom GLFW_SELECTION;
|
Atom GLFW_SELECTION;
|
||||||
|
|
||||||
|
// Format atoms (shared by Xdnd and Selection)
|
||||||
|
Atom NULL_;
|
||||||
|
Atom UTF8_STRING;
|
||||||
|
Atom STRING;
|
||||||
|
Atom TEXT;
|
||||||
|
Atom text_plain;
|
||||||
|
Atom text_uri_list;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
void* handle;
|
void* handle;
|
||||||
GLFWbool utf8;
|
GLFWbool utf8;
|
||||||
@ -800,7 +808,12 @@ typedef struct _GLFWlibraryX11
|
|||||||
struct {
|
struct {
|
||||||
int version;
|
int version;
|
||||||
Window source;
|
Window source;
|
||||||
Atom format;
|
Atom formatAtoms[_GLFW_DND_FORMAT_COUNT];
|
||||||
|
int availableFormats;
|
||||||
|
int chosenFormat;
|
||||||
|
int availableActions;
|
||||||
|
int proposedAction;
|
||||||
|
int chosenAction;
|
||||||
} xdnd;
|
} xdnd;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
138
src/x11_window.c
138
src/x11_window.c
@ -1519,15 +1519,22 @@ static void processEvent(XEvent *event)
|
|||||||
// A drag operation has entered the window
|
// A drag operation has entered the window
|
||||||
unsigned long count;
|
unsigned long count;
|
||||||
Atom* formats = NULL;
|
Atom* formats = NULL;
|
||||||
|
double xpos, ypos;
|
||||||
const GLFWbool list = event->xclient.data.l[1] & 1;
|
const GLFWbool list = event->xclient.data.l[1] & 1;
|
||||||
|
|
||||||
|
memset(&_glfw.x11.xdnd, 0, sizeof(_glfw.x11.xdnd));
|
||||||
_glfw.x11.xdnd.source = event->xclient.data.l[0];
|
_glfw.x11.xdnd.source = event->xclient.data.l[0];
|
||||||
_glfw.x11.xdnd.version = event->xclient.data.l[1] >> 24;
|
_glfw.x11.xdnd.version = event->xclient.data.l[1] >> 24;
|
||||||
_glfw.x11.xdnd.format = None;
|
|
||||||
|
|
||||||
if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
|
if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Xdnd doesn't support the concepts "available actions" and
|
||||||
|
// "proposed action"; default to all and copy
|
||||||
|
_glfw.x11.xdnd.availableActions =
|
||||||
|
GLFW_DND_COPY | GLFW_DND_LINK | GLFW_DND_MOVE;
|
||||||
|
_glfw.x11.xdnd.proposedAction = GLFW_DND_COPY;
|
||||||
|
|
||||||
if (list)
|
if (list)
|
||||||
{
|
{
|
||||||
count = _glfwGetWindowPropertyX11(_glfw.x11.xdnd.source,
|
count = _glfwGetWindowPropertyX11(_glfw.x11.xdnd.source,
|
||||||
@ -1541,27 +1548,75 @@ static void processEvent(XEvent *event)
|
|||||||
formats = (Atom*) event->xclient.data.l + 2;
|
formats = (Atom*) event->xclient.data.l + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO remove
|
||||||
|
PFN_XGetAtomName GetAtomName = (PFN_XGetAtomName)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetAtomName");
|
||||||
for (unsigned int i = 0; i < count; i++)
|
for (unsigned int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
if (formats[i] == _glfw.x11.text_uri_list)
|
printf("format (%d): %s\n", i, GetAtomName(_glfw.x11.display, formats[i]));
|
||||||
|
if (!_glfw.x11.xdnd.formatAtoms[_GLFW_DND_PATHS_INDEX]
|
||||||
|
&& formats[i] == _glfw.x11.text_uri_list)
|
||||||
{
|
{
|
||||||
_glfw.x11.xdnd.format = _glfw.x11.text_uri_list;
|
_glfw.x11.xdnd.formatAtoms[_GLFW_DND_PATHS_INDEX] = formats[i];
|
||||||
break;
|
_glfw.x11.xdnd.availableFormats |= GLFW_DND_PATHS;
|
||||||
|
}
|
||||||
|
else if (!_glfw.x11.xdnd.formatAtoms[_GLFW_DND_TEXT_INDEX]
|
||||||
|
&& (formats[i] == _glfw.x11.text_plain
|
||||||
|
|| formats[i] == _glfw.x11.UTF8_STRING
|
||||||
|
|| formats[i] == _glfw.x11.STRING
|
||||||
|
|| formats[i] == _glfw.x11.TEXT))
|
||||||
|
{
|
||||||
|
_glfw.x11.xdnd.formatAtoms[_GLFW_DND_TEXT_INDEX] = formats[i];
|
||||||
|
_glfw.x11.xdnd.availableFormats |= GLFW_DND_TEXT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list && formats)
|
if (list && formats)
|
||||||
XFree(formats);
|
XFree(formats);
|
||||||
|
|
||||||
|
window->dndDragging = GLFW_TRUE;
|
||||||
|
|
||||||
|
_glfwGetCursorPosX11(window, &xpos, &ypos);
|
||||||
|
|
||||||
|
_glfw.x11.xdnd.chosenFormat = _glfw.x11.xdnd.availableFormats;
|
||||||
|
_glfw.x11.xdnd.chosenAction = _glfw.x11.xdnd.proposedAction;
|
||||||
|
_glfwInputDrag(window, GLFW_DND_ENTER, xpos, ypos,
|
||||||
|
_glfw.x11.xdnd.availableFormats,
|
||||||
|
&_glfw.x11.xdnd.chosenFormat,
|
||||||
|
_glfw.x11.xdnd.availableActions,
|
||||||
|
&_glfw.x11.xdnd.chosenAction);
|
||||||
|
}
|
||||||
|
else if (event->xclient.message_type == _glfw.x11.XdndLeave)
|
||||||
|
{
|
||||||
|
// A drag operation has left the window or was canceled
|
||||||
|
window->dndDragging = GLFW_FALSE;
|
||||||
|
|
||||||
|
_glfw.x11.xdnd.chosenFormat =
|
||||||
|
_glfw.x11.xdnd.availableFormats = GLFW_DND_NONE;
|
||||||
|
_glfw.x11.xdnd.chosenAction =
|
||||||
|
_glfw.x11.xdnd.proposedAction =
|
||||||
|
_glfw.x11.xdnd.availableActions = GLFW_DND_NONE;
|
||||||
|
_glfwInputDrag(window, GLFW_DND_LEAVE, 0.0, 0.0,
|
||||||
|
_glfw.x11.xdnd.availableFormats,
|
||||||
|
&_glfw.x11.xdnd.chosenFormat,
|
||||||
|
_glfw.x11.xdnd.availableActions,
|
||||||
|
&_glfw.x11.xdnd.chosenAction);
|
||||||
}
|
}
|
||||||
else if (event->xclient.message_type == _glfw.x11.XdndDrop)
|
else if (event->xclient.message_type == _glfw.x11.XdndDrop)
|
||||||
{
|
{
|
||||||
// The drag operation has finished by dropping on the window
|
// The drag operation has finished by dropping on the window
|
||||||
Time time = CurrentTime;
|
Time time = CurrentTime;
|
||||||
|
int formatIndex = _glfw_ffs(_glfw.x11.xdnd.chosenFormat
|
||||||
|
& _GLFW_DND_MASK) - 1;
|
||||||
|
|
||||||
|
window->dndDragging = GLFW_FALSE;
|
||||||
|
|
||||||
if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
|
if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_glfw.x11.xdnd.format)
|
if (_glfw.x11.xdnd.chosenAction
|
||||||
|
&& formatIndex >= 0 && formatIndex < _GLFW_DND_FORMAT_COUNT
|
||||||
|
&& _glfw.x11.xdnd.formatAtoms[formatIndex])
|
||||||
{
|
{
|
||||||
if (_glfw.x11.xdnd.version >= 1)
|
if (_glfw.x11.xdnd.version >= 1)
|
||||||
time = event->xclient.data.l[2];
|
time = event->xclient.data.l[2];
|
||||||
@ -1569,7 +1624,7 @@ static void processEvent(XEvent *event)
|
|||||||
// Request the chosen format from the source window
|
// Request the chosen format from the source window
|
||||||
XConvertSelection(_glfw.x11.display,
|
XConvertSelection(_glfw.x11.display,
|
||||||
_glfw.x11.XdndSelection,
|
_glfw.x11.XdndSelection,
|
||||||
_glfw.x11.xdnd.format,
|
_glfw.x11.xdnd.formatAtoms[formatIndex],
|
||||||
_glfw.x11.XdndSelection,
|
_glfw.x11.XdndSelection,
|
||||||
window->x11.handle,
|
window->x11.handle,
|
||||||
time);
|
time);
|
||||||
@ -1594,12 +1649,29 @@ static void processEvent(XEvent *event)
|
|||||||
// The drag operation has moved over the window
|
// The drag operation has moved over the window
|
||||||
const int xabs = (event->xclient.data.l[2] >> 16) & 0xffff;
|
const int xabs = (event->xclient.data.l[2] >> 16) & 0xffff;
|
||||||
const int yabs = (event->xclient.data.l[2]) & 0xffff;
|
const int yabs = (event->xclient.data.l[2]) & 0xffff;
|
||||||
|
const Atom action = event->xclient.data.l[4];
|
||||||
Window dummy;
|
Window dummy;
|
||||||
int xpos, ypos;
|
int xpos, ypos;
|
||||||
|
|
||||||
if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
|
if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (_glfw.x11.xdnd.version >= 2)
|
||||||
|
{
|
||||||
|
_glfw.x11.xdnd.proposedAction = GLFW_DND_NONE;
|
||||||
|
for(int i = 0; i < _GLFW_DND_ACTION_COUNT; ++i)
|
||||||
|
{
|
||||||
|
if(action == _glfw.x11.XdndActions[i])
|
||||||
|
{
|
||||||
|
_glfw.x11.xdnd.proposedAction =
|
||||||
|
(GLFW_DND_COPY & ~_GLFW_DND_MASK) | (1 << i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_glfw.x11.xdnd.proposedAction = GLFW_DND_COPY;
|
||||||
|
|
||||||
XTranslateCoordinates(_glfw.x11.display,
|
XTranslateCoordinates(_glfw.x11.display,
|
||||||
_glfw.x11.root,
|
_glfw.x11.root,
|
||||||
window->x11.handle,
|
window->x11.handle,
|
||||||
@ -1609,6 +1681,13 @@ static void processEvent(XEvent *event)
|
|||||||
|
|
||||||
_glfwInputCursorPos(window, xpos, ypos);
|
_glfwInputCursorPos(window, xpos, ypos);
|
||||||
|
|
||||||
|
_glfw.x11.xdnd.chosenAction = _glfw.x11.xdnd.proposedAction;
|
||||||
|
_glfwInputDrag(window, GLFW_DND_DRAG, xpos, ypos,
|
||||||
|
_glfw.x11.xdnd.availableFormats,
|
||||||
|
&_glfw.x11.xdnd.chosenFormat,
|
||||||
|
_glfw.x11.xdnd.availableActions,
|
||||||
|
&_glfw.x11.xdnd.chosenAction);
|
||||||
|
|
||||||
XEvent reply = { ClientMessage };
|
XEvent reply = { ClientMessage };
|
||||||
reply.xclient.window = _glfw.x11.xdnd.source;
|
reply.xclient.window = _glfw.x11.xdnd.source;
|
||||||
reply.xclient.message_type = _glfw.x11.XdndStatus;
|
reply.xclient.message_type = _glfw.x11.XdndStatus;
|
||||||
@ -1617,12 +1696,19 @@ static void processEvent(XEvent *event)
|
|||||||
reply.xclient.data.l[2] = 0; // Specify an empty rectangle
|
reply.xclient.data.l[2] = 0; // Specify an empty rectangle
|
||||||
reply.xclient.data.l[3] = 0;
|
reply.xclient.data.l[3] = 0;
|
||||||
|
|
||||||
if (_glfw.x11.xdnd.format)
|
if (_glfw.x11.xdnd.chosenAction)
|
||||||
{
|
{
|
||||||
// Reply that we are ready to copy the dragged data
|
// Reply that we are ready to copy the dragged data
|
||||||
reply.xclient.data.l[1] = 1; // Accept with no rectangle
|
reply.xclient.data.l[1] = 1; // Accept with no rectangle
|
||||||
if (_glfw.x11.xdnd.version >= 2)
|
if (_glfw.x11.xdnd.version >= 2)
|
||||||
reply.xclient.data.l[4] = _glfw.x11.XdndActionCopy;
|
{
|
||||||
|
int actionIndex = _glfw_ffs(_glfw.x11.xdnd.chosenAction
|
||||||
|
& _GLFW_DND_MASK) - 1;
|
||||||
|
if(actionIndex >= 0 && actionIndex < _GLFW_DND_ACTION_COUNT)
|
||||||
|
{
|
||||||
|
reply.xclient.data.l[4] = _glfw.x11.XdndActions[actionIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source,
|
XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source,
|
||||||
@ -1646,15 +1732,39 @@ static void processEvent(XEvent *event)
|
|||||||
(unsigned char**) &data);
|
(unsigned char**) &data);
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
|
{
|
||||||
|
int formatIndex = _glfw_ffs(_glfw.x11.xdnd.chosenFormat
|
||||||
|
& _GLFW_DND_MASK) - 1;
|
||||||
|
if(formatIndex >= 0 && formatIndex < _GLFW_DND_FORMAT_COUNT)
|
||||||
|
{
|
||||||
|
int format = (GLFW_DND_TEXT & ~_GLFW_DND_MASK) | (1 << formatIndex);
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case GLFW_DND_PATHS:
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
char** paths = _glfwParseUriList(data, &count);
|
char** paths = _glfwParseUriList(data, &count);
|
||||||
|
|
||||||
_glfwInputDrop(window, count, (const char**) paths);
|
_glfwInputDrop(window, count, (const char **) paths);
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
_glfwInputDropEx(window, format, count, paths,
|
||||||
|
&_glfw.x11.xdnd.chosenAction);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
_glfw_free(paths[i]);
|
_glfw_free(paths[i]);
|
||||||
_glfw_free(paths);
|
_glfw_free(paths);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GLFW_DND_TEXT:
|
||||||
|
{
|
||||||
|
_glfwInputDropEx(window, format, -1, data,
|
||||||
|
&_glfw.x11.xdnd.chosenAction);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data)
|
if (data)
|
||||||
@ -1668,7 +1778,13 @@ static void processEvent(XEvent *event)
|
|||||||
reply.xclient.format = 32;
|
reply.xclient.format = 32;
|
||||||
reply.xclient.data.l[0] = window->x11.handle;
|
reply.xclient.data.l[0] = window->x11.handle;
|
||||||
reply.xclient.data.l[1] = result;
|
reply.xclient.data.l[1] = result;
|
||||||
reply.xclient.data.l[2] = _glfw.x11.XdndActionCopy;
|
|
||||||
|
int actionIndex = _glfw_ffs(_glfw.x11.xdnd.chosenAction
|
||||||
|
& _GLFW_DND_MASK) - 1;
|
||||||
|
if(actionIndex >= 0 && actionIndex < _GLFW_DND_ACTION_COUNT)
|
||||||
|
{
|
||||||
|
reply.xclient.data.l[2] = _glfw.x11.XdndActions[actionIndex];
|
||||||
|
}
|
||||||
|
|
||||||
XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source,
|
XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source,
|
||||||
False, NoEventMask, &reply);
|
False, NoEventMask, &reply);
|
||||||
|
Loading…
Reference in New Issue
Block a user