mirror of
https://github.com/glfw/glfw.git
synced 2025-06-08 00:34:56 +00:00
Merge d010d61f87
into 3a60992a41
This commit is contained in:
commit
0ad98d3f74
@ -80,8 +80,89 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
|
|||||||
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drag_callback(GLFWwindow* window, int event, double xpos, double ypos, int availableFormats, int *format, int availableActions, int *action)
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
glfwGetWindowSize(window, &width, &height);
|
||||||
|
switch(event)
|
||||||
|
{
|
||||||
|
case GLFW_DND_ENTER:
|
||||||
|
{
|
||||||
|
printf("ENTER (%d, %d)\n", (int)xpos, (int)ypos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GLFW_DND_DRAG:
|
||||||
|
{
|
||||||
|
printf("DRAG (%d, %d)\n", (int)xpos, (int)ypos);
|
||||||
|
|
||||||
|
if ((int) xpos < (width / 2))
|
||||||
|
{
|
||||||
|
if ((availableFormats & GLFW_DND_PATHS) == GLFW_DND_PATHS)
|
||||||
|
{
|
||||||
|
printf("accepting paths\n");
|
||||||
|
*format = GLFW_DND_PATHS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("reject\n");
|
||||||
|
*action = GLFW_DND_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ((availableFormats & GLFW_DND_TEXT) == GLFW_DND_TEXT)
|
||||||
|
{
|
||||||
|
printf("accepting text\n");
|
||||||
|
*format = GLFW_DND_TEXT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("reject\n");
|
||||||
|
*action = GLFW_DND_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GLFW_DND_LEAVE:
|
||||||
|
{
|
||||||
|
printf("LEAVE\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drop_callback(GLFWwindow* window, int count, const char** paths)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
printf("path[%d]: %s\n", i, paths[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dropex_callback(GLFWwindow* window, int format, int data_count, void *data, int *action)
|
||||||
|
{
|
||||||
|
printf("DROP\n");
|
||||||
|
|
||||||
|
switch(format)
|
||||||
|
{
|
||||||
|
case GLFW_DND_PATHS:
|
||||||
|
{
|
||||||
|
const char **paths = (const char **) data;
|
||||||
|
for(int i = 0; i < data_count; ++i)
|
||||||
|
printf("path[%d]: %s\n", i, paths[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GLFW_DND_TEXT:
|
||||||
|
printf("text: %s\n", (const char *) data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
(void)setvbuf(stdout, NULL, _IONBF, 0);
|
||||||
|
(void)setvbuf(stderr, NULL, _IONBF, 0);
|
||||||
|
|
||||||
glfwSetErrorCallback(error_callback);
|
glfwSetErrorCallback(error_callback);
|
||||||
|
|
||||||
if (!glfwInit())
|
if (!glfwInit())
|
||||||
@ -99,6 +180,9 @@ int main(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
glfwSetKeyCallback(window, key_callback);
|
glfwSetKeyCallback(window, key_callback);
|
||||||
|
glfwSetDragCallback(window, drag_callback);
|
||||||
|
glfwSetDropCallback(window, drop_callback);
|
||||||
|
glfwSetDropCallbackEx(window, dropex_callback);
|
||||||
|
|
||||||
glfwMakeContextCurrent(window);
|
glfwMakeContextCurrent(window);
|
||||||
gladLoadGL(glfwGetProcAddress);
|
gladLoadGL(glfwGetProcAddress);
|
||||||
@ -149,6 +233,7 @@ int main(void)
|
|||||||
|
|
||||||
mat4x4 m, p, mvp;
|
mat4x4 m, p, mvp;
|
||||||
mat4x4_identity(m);
|
mat4x4_identity(m);
|
||||||
|
if (glfwGetWindowAttrib(window, GLFW_DND_DRAGGING))
|
||||||
mat4x4_rotate_Z(m, m, (float) glfwGetTime());
|
mat4x4_rotate_Z(m, m, (float) glfwGetTime());
|
||||||
mat4x4_ortho(p, -ratio, ratio, -1.f, 1.f, 1.f, -1.f);
|
mat4x4_ortho(p, -ratio, ratio, -1.f, 1.f, 1.f, -1.f);
|
||||||
mat4x4_mul(mvp, p, m);
|
mat4x4_mul(mvp, p, m);
|
||||||
|
@ -927,6 +927,9 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
#define GLFW_MOUSE_PASSTHROUGH 0x0002000D
|
#define GLFW_MOUSE_PASSTHROUGH 0x0002000D
|
||||||
|
|
||||||
|
// TODO doc
|
||||||
|
#define GLFW_DND_DRAGGING 0x0002000E
|
||||||
|
|
||||||
/*! @brief Framebuffer bit depth hint.
|
/*! @brief Framebuffer bit depth hint.
|
||||||
*
|
*
|
||||||
* Framebuffer bit depth [hint](@ref GLFW_RED_BITS).
|
* Framebuffer bit depth [hint](@ref GLFW_RED_BITS).
|
||||||
@ -1309,6 +1312,25 @@ extern "C" {
|
|||||||
#define GLFW_PLATFORM_NULL 0x00060005
|
#define GLFW_PLATFORM_NULL 0x00060005
|
||||||
/*! @} */
|
/*! @} */
|
||||||
|
|
||||||
|
// TODO doc
|
||||||
|
#define GLFW_DND_NONE 0
|
||||||
|
|
||||||
|
// Drag and drop events
|
||||||
|
#define GLFW_DND_ENTER 0xdd100001
|
||||||
|
#define GLFW_DND_DRAG 0xdd100002
|
||||||
|
#define GLFW_DND_LEAVE 0xdd100003
|
||||||
|
|
||||||
|
// Drag and drop actions
|
||||||
|
// GLFW_DND_NONE
|
||||||
|
#define GLFW_DND_COPY 0xdd200001
|
||||||
|
#define GLFW_DND_LINK 0xdd200002
|
||||||
|
#define GLFW_DND_MOVE 0xdd200004
|
||||||
|
|
||||||
|
// Drag and drop formats
|
||||||
|
// GLFW_DND_NONE
|
||||||
|
#define GLFW_DND_TEXT 0xdd300002
|
||||||
|
#define GLFW_DND_PATHS 0xdd300001
|
||||||
|
|
||||||
#define GLFW_DONT_CARE -1
|
#define GLFW_DONT_CARE -1
|
||||||
|
|
||||||
|
|
||||||
@ -1884,6 +1906,9 @@ typedef void (* GLFWcharfun)(GLFWwindow* window, unsigned int codepoint);
|
|||||||
*/
|
*/
|
||||||
typedef void (* GLFWcharmodsfun)(GLFWwindow* window, unsigned int codepoint, int mods);
|
typedef void (* GLFWcharmodsfun)(GLFWwindow* window, unsigned int codepoint, int mods);
|
||||||
|
|
||||||
|
// TODO doc
|
||||||
|
typedef void (* GLFWdragfun)(GLFWwindow* window, int event, double xpos, double ypos, int availableFormats, int *format, int availableActions, int *action);
|
||||||
|
|
||||||
/*! @brief The function pointer type for path drop callbacks.
|
/*! @brief The function pointer type for path drop callbacks.
|
||||||
*
|
*
|
||||||
* This is the function pointer type for path drop callbacks. A path drop
|
* This is the function pointer type for path drop callbacks. A path drop
|
||||||
@ -1908,6 +1933,9 @@ typedef void (* GLFWcharmodsfun)(GLFWwindow* window, unsigned int codepoint, int
|
|||||||
*/
|
*/
|
||||||
typedef void (* GLFWdropfun)(GLFWwindow* window, int path_count, const char* paths[]);
|
typedef void (* GLFWdropfun)(GLFWwindow* window, int path_count, const char* paths[]);
|
||||||
|
|
||||||
|
// TODO doc
|
||||||
|
typedef void (* GLFWdropfunex)(GLFWwindow* window, int format, int data_count, void *data, int *action);
|
||||||
|
|
||||||
/*! @brief The function pointer type for monitor configuration callbacks.
|
/*! @brief The function pointer type for monitor configuration callbacks.
|
||||||
*
|
*
|
||||||
* This is the function pointer type for monitor configuration callbacks.
|
* This is the function pointer type for monitor configuration callbacks.
|
||||||
@ -5293,6 +5321,9 @@ GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* window, GLFWcu
|
|||||||
*/
|
*/
|
||||||
GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun callback);
|
GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun callback);
|
||||||
|
|
||||||
|
// TODO doc
|
||||||
|
GLFWAPI GLFWdragfun glfwSetDragCallback(GLFWwindow* window, GLFWdragfun callback);
|
||||||
|
|
||||||
/*! @brief Sets the path drop callback.
|
/*! @brief Sets the path drop callback.
|
||||||
*
|
*
|
||||||
* This function sets the path drop callback of the specified window, which is
|
* This function sets the path drop callback of the specified window, which is
|
||||||
@ -5330,6 +5361,9 @@ GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun ca
|
|||||||
*/
|
*/
|
||||||
GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun callback);
|
GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun callback);
|
||||||
|
|
||||||
|
// TODO doc
|
||||||
|
GLFWAPI GLFWdropfunex glfwSetDropCallbackEx(GLFWwindow* window, GLFWdropfunex callback);
|
||||||
|
|
||||||
/*! @brief Returns whether the specified joystick is present.
|
/*! @brief Returns whether the specified joystick is present.
|
||||||
*
|
*
|
||||||
* This function returns whether the specified joystick is present.
|
* This function returns whether the specified joystick is present.
|
||||||
|
35
src/init.c
35
src/init.c
@ -266,6 +266,41 @@ float _glfw_fmaxf(float a, float b)
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _glfw_ffs(int i)
|
||||||
|
{
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
return __builtin_ffs(i);
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
unsigned long n, u = i;
|
||||||
|
return _BitScanForward(&n, u) ? n + 1 : 0;
|
||||||
|
#else
|
||||||
|
// https://en.wikipedia.org/wiki/Find_first_set#CTZ
|
||||||
|
unsigned int u = i;
|
||||||
|
int n = 1;
|
||||||
|
if (!u) return 0;
|
||||||
|
if (!(u & 0x0000FFFF)) {
|
||||||
|
n += 16;
|
||||||
|
u >>= 16;
|
||||||
|
}
|
||||||
|
if (!(u & 0x000000FF)) {
|
||||||
|
n += 8;
|
||||||
|
u >>= 8;
|
||||||
|
}
|
||||||
|
if (!(u & 0x0000000F)) {
|
||||||
|
n += 4;
|
||||||
|
u >>= 4;
|
||||||
|
}
|
||||||
|
if (!(u & 0x00000003)) {
|
||||||
|
n += 2;
|
||||||
|
u >>= 2;
|
||||||
|
}
|
||||||
|
if (!(u & 0x00000001)) {
|
||||||
|
n += 1;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void* _glfw_calloc(size_t count, size_t size)
|
void* _glfw_calloc(size_t count, size_t size)
|
||||||
{
|
{
|
||||||
if (count && size)
|
if (count && size)
|
||||||
|
36
src/input.c
36
src/input.c
@ -401,6 +401,14 @@ void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered)
|
|||||||
window->callbacks.cursorEnter((GLFWwindow*) window, entered);
|
window->callbacks.cursorEnter((GLFWwindow*) window, entered);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notifies shared code of data being dragged in/over/out of a window
|
||||||
|
//
|
||||||
|
void _glfwInputDrag(_GLFWwindow* window, int event, double xpos, double ypos, int availableFormats, int *format, int availableActions, int *action)
|
||||||
|
{
|
||||||
|
if (window->callbacks.drag)
|
||||||
|
window->callbacks.drag((GLFWwindow*) window, event, xpos, ypos, availableFormats, format, availableActions, action);
|
||||||
|
}
|
||||||
|
|
||||||
// Notifies shared code of files or directories dropped on a window
|
// Notifies shared code of files or directories dropped on a window
|
||||||
//
|
//
|
||||||
void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
|
void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
|
||||||
@ -413,6 +421,14 @@ void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
|
|||||||
window->callbacks.drop((GLFWwindow*) window, count, paths);
|
window->callbacks.drop((GLFWwindow*) window, count, paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notifies shared code of data dropped on a window
|
||||||
|
//
|
||||||
|
void _glfwInputDropEx(_GLFWwindow* window, int format, int data_count, void *data, int *action)
|
||||||
|
{
|
||||||
|
if (window->callbacks.dropex)
|
||||||
|
window->callbacks.dropex((GLFWwindow*) window, format, data_count, data, action);
|
||||||
|
}
|
||||||
|
|
||||||
// Notifies shared code of a joystick connection or disconnection
|
// Notifies shared code of a joystick connection or disconnection
|
||||||
//
|
//
|
||||||
void _glfwInputJoystick(_GLFWjoystick* js, int event)
|
void _glfwInputJoystick(_GLFWjoystick* js, int event)
|
||||||
@ -1012,6 +1028,16 @@ GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* handle,
|
|||||||
return cbfun;
|
return cbfun;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWdragfun glfwSetDragCallback(GLFWwindow* handle, GLFWdragfun cbfun)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP(GLFWdragfun, window->callbacks.drag, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
||||||
GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun)
|
GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
@ -1022,6 +1048,16 @@ GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun)
|
|||||||
return cbfun;
|
return cbfun;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWdropfunex glfwSetDropCallbackEx(GLFWwindow* handle, GLFWdropfunex cbfun)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP(GLFWdropfunex, window->callbacks.dropex, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
||||||
GLFWAPI int glfwJoystickPresent(int jid)
|
GLFWAPI int glfwJoystickPresent(int jid)
|
||||||
{
|
{
|
||||||
_GLFWjoystick* js;
|
_GLFWjoystick* js;
|
||||||
|
@ -58,6 +58,17 @@
|
|||||||
|
|
||||||
#define _GLFW_MESSAGE_SIZE 1024
|
#define _GLFW_MESSAGE_SIZE 1024
|
||||||
|
|
||||||
|
#define _GLFW_DND_MASK 0x000fffff
|
||||||
|
|
||||||
|
#define _GLFW_DND_TEXT_INDEX 1
|
||||||
|
#define _GLFW_DND_PATHS_INDEX 0
|
||||||
|
#define _GLFW_DND_FORMAT_COUNT 2
|
||||||
|
|
||||||
|
#define _GLFW_DND_COPY_INDEX 0
|
||||||
|
#define _GLFW_DND_LINK_INDEX 1
|
||||||
|
#define _GLFW_DND_MOVE_INDEX 2
|
||||||
|
#define _GLFW_DND_ACTION_COUNT 3
|
||||||
|
|
||||||
typedef int GLFWbool;
|
typedef int GLFWbool;
|
||||||
typedef void (*GLFWproc)(void);
|
typedef void (*GLFWproc)(void);
|
||||||
|
|
||||||
@ -533,6 +544,7 @@ struct _GLFWwindow
|
|||||||
GLFWbool floating;
|
GLFWbool floating;
|
||||||
GLFWbool focusOnShow;
|
GLFWbool focusOnShow;
|
||||||
GLFWbool mousePassthrough;
|
GLFWbool mousePassthrough;
|
||||||
|
GLFWbool dndDragging;
|
||||||
GLFWbool shouldClose;
|
GLFWbool shouldClose;
|
||||||
void* userPointer;
|
void* userPointer;
|
||||||
GLFWbool doublebuffer;
|
GLFWbool doublebuffer;
|
||||||
@ -573,7 +585,9 @@ struct _GLFWwindow
|
|||||||
GLFWkeyfun key;
|
GLFWkeyfun key;
|
||||||
GLFWcharfun character;
|
GLFWcharfun character;
|
||||||
GLFWcharmodsfun charmods;
|
GLFWcharmodsfun charmods;
|
||||||
|
GLFWdragfun drag;
|
||||||
GLFWdropfun drop;
|
GLFWdropfun drop;
|
||||||
|
GLFWdropfunex dropex;
|
||||||
} callbacks;
|
} callbacks;
|
||||||
|
|
||||||
// This is defined in platform.h
|
// This is defined in platform.h
|
||||||
@ -928,7 +942,9 @@ void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset);
|
|||||||
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
|
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
|
||||||
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
||||||
void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered);
|
void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered);
|
||||||
|
void _glfwInputDrag(_GLFWwindow* window, int event, double xpos, double ypos, int availableFormats, int *format, int availableActions, int *action);
|
||||||
void _glfwInputDrop(_GLFWwindow* window, int count, const char** names);
|
void _glfwInputDrop(_GLFWwindow* window, int count, const char** names);
|
||||||
|
void _glfwInputDropEx(_GLFWwindow* window, int format, int data_count, void *data, int *action);
|
||||||
void _glfwInputJoystick(_GLFWjoystick* js, int event);
|
void _glfwInputJoystick(_GLFWjoystick* js, int event);
|
||||||
void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value);
|
void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value);
|
||||||
void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value);
|
void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value);
|
||||||
@ -1007,6 +1023,7 @@ int _glfw_min(int a, int b);
|
|||||||
int _glfw_max(int a, int b);
|
int _glfw_max(int a, int b);
|
||||||
float _glfw_fminf(float a, float b);
|
float _glfw_fminf(float a, float b);
|
||||||
float _glfw_fmaxf(float a, float b);
|
float _glfw_fmaxf(float a, float b);
|
||||||
|
int _glfw_ffs(int i);
|
||||||
|
|
||||||
void* _glfw_calloc(size_t count, size_t size);
|
void* _glfw_calloc(size_t count, size_t size);
|
||||||
void* _glfw_realloc(void* pointer, size_t size);
|
void* _glfw_realloc(void* pointer, size_t size);
|
||||||
|
@ -167,6 +167,19 @@ static GLFWbool loadLibraries(void)
|
|||||||
_glfwPlatformGetModuleSymbol(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo");
|
_glfwPlatformGetModuleSymbol(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_glfw.win32.ole32.instance = _glfwPlatformLoadModule("ole32.dll");
|
||||||
|
if (_glfw.win32.ole32.instance)
|
||||||
|
{
|
||||||
|
_glfw.win32.ole32.OleInitialize_ = (PFN_OleInitialize)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.win32.ole32.instance, "OleInitialize");
|
||||||
|
_glfw.win32.ole32.OleUninitialize_ = (PFN_OleUninitialize)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.win32.ole32.instance, "OleUninitialize");
|
||||||
|
_glfw.win32.ole32.RegisterDragDrop_ = (PFN_RegisterDragDrop)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.win32.ole32.instance, "RegisterDragDrop");
|
||||||
|
_glfw.win32.ole32.RevokeDragDrop_ = (PFN_RevokeDragDrop)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.win32.ole32.instance, "RevokeDragDrop");
|
||||||
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,6 +204,9 @@ static void freeLibraries(void)
|
|||||||
|
|
||||||
if (_glfw.win32.ntdll.instance)
|
if (_glfw.win32.ntdll.instance)
|
||||||
_glfwPlatformFreeModule(_glfw.win32.ntdll.instance);
|
_glfwPlatformFreeModule(_glfw.win32.ntdll.instance);
|
||||||
|
|
||||||
|
if (_glfw.win32.ole32.instance)
|
||||||
|
_glfwPlatformFreeModule(_glfw.win32.ole32.instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create key code translation tables
|
// Create key code translation tables
|
||||||
@ -430,6 +446,27 @@ static GLFWbool createHelperWindow(void)
|
|||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize OLE as well as the IDropTarget vtable
|
||||||
|
//
|
||||||
|
static GLFWbool initDragDrop()
|
||||||
|
{
|
||||||
|
if (FAILED(OleInitialize(NULL)))
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to initialize OLE");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//_glfw.win32.dropTargetVtbl.QueryInterface = _glfwDropTarget_QueryInterface;
|
||||||
|
_glfw.win32.dropTargetVtbl.AddRef = _glfwDropTarget_AddRef;
|
||||||
|
_glfw.win32.dropTargetVtbl.Release = _glfwDropTarget_Release;
|
||||||
|
_glfw.win32.dropTargetVtbl.DragEnter = _glfwDropTarget_DragEnter;
|
||||||
|
_glfw.win32.dropTargetVtbl.DragOver = _glfwDropTarget_DragOver;
|
||||||
|
_glfw.win32.dropTargetVtbl.DragLeave = _glfwDropTarget_DragLeave;
|
||||||
|
_glfw.win32.dropTargetVtbl.Drop = _glfwDropTarget_Drop;
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW internal API //////
|
////// GLFW internal API //////
|
||||||
@ -699,6 +736,9 @@ int _glfwInitWin32(void)
|
|||||||
if (!createHelperWindow())
|
if (!createHelperWindow())
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
if (!initDragDrop())
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
_glfwPollMonitorsWin32();
|
_glfwPollMonitorsWin32();
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
@ -708,6 +748,8 @@ void _glfwTerminateWin32(void)
|
|||||||
if (_glfw.win32.deviceNotificationHandle)
|
if (_glfw.win32.deviceNotificationHandle)
|
||||||
UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle);
|
UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle);
|
||||||
|
|
||||||
|
OleUninitialize();
|
||||||
|
|
||||||
if (_glfw.win32.helperWindowHandle)
|
if (_glfw.win32.helperWindowHandle)
|
||||||
DestroyWindow(_glfw.win32.helperWindowHandle);
|
DestroyWindow(_glfw.win32.helperWindowHandle);
|
||||||
if (_glfw.win32.helperWindowClass)
|
if (_glfw.win32.helperWindowClass)
|
||||||
|
@ -64,11 +64,15 @@
|
|||||||
// GLFW uses OEM cursor resources
|
// GLFW uses OEM cursor resources
|
||||||
#define OEMRESOURCE
|
#define OEMRESOURCE
|
||||||
|
|
||||||
|
// define COM C object macros
|
||||||
|
#define COBJMACROS
|
||||||
|
|
||||||
#include <wctype.h>
|
#include <wctype.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <dinput.h>
|
#include <dinput.h>
|
||||||
#include <xinput.h>
|
#include <xinput.h>
|
||||||
#include <dbt.h>
|
#include <dbt.h>
|
||||||
|
#include <ole2.h>
|
||||||
|
|
||||||
// HACK: Define macros that some windows.h variants don't
|
// HACK: Define macros that some windows.h variants don't
|
||||||
#ifndef WM_MOUSEHWHEEL
|
#ifndef WM_MOUSEHWHEEL
|
||||||
@ -316,6 +320,16 @@ typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,
|
|||||||
typedef LONG (WINAPI * PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*,ULONG,ULONGLONG);
|
typedef LONG (WINAPI * PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*,ULONG,ULONGLONG);
|
||||||
#define RtlVerifyVersionInfo _glfw.win32.ntdll.RtlVerifyVersionInfo_
|
#define RtlVerifyVersionInfo _glfw.win32.ntdll.RtlVerifyVersionInfo_
|
||||||
|
|
||||||
|
// ole32.dll function pointer typedefs
|
||||||
|
typedef HRESULT (WINAPI * PFN_OleInitialize)(LPVOID);
|
||||||
|
typedef VOID (WINAPI * PFN_OleUninitialize)(VOID);
|
||||||
|
typedef HRESULT (WINAPI * PFN_RegisterDragDrop)(HWND,LPDROPTARGET);
|
||||||
|
typedef HRESULT (WINAPI * PFN_RevokeDragDrop)(HWND);
|
||||||
|
#define OleInitialize _glfw.win32.ole32.OleInitialize_
|
||||||
|
#define OleUninitialize _glfw.win32.ole32.OleUninitialize_
|
||||||
|
#define RegisterDragDrop _glfw.win32.ole32.RegisterDragDrop_
|
||||||
|
#define RevokeDragDrop _glfw.win32.ole32.RevokeDragDrop_
|
||||||
|
|
||||||
// WGL extension pointer typedefs
|
// WGL extension pointer typedefs
|
||||||
typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int);
|
typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int);
|
||||||
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*);
|
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*);
|
||||||
@ -408,6 +422,18 @@ typedef struct _GLFWlibraryWGL
|
|||||||
GLFWbool ARB_context_flush_control;
|
GLFWbool ARB_context_flush_control;
|
||||||
} _GLFWlibraryWGL;
|
} _GLFWlibraryWGL;
|
||||||
|
|
||||||
|
typedef struct _GLFWdroptarget
|
||||||
|
{
|
||||||
|
IDropTargetVtbl* lpVtbl;
|
||||||
|
ULONG cRefCount;
|
||||||
|
_GLFWwindow* window;
|
||||||
|
int availableFormats;
|
||||||
|
int chosenFormat;
|
||||||
|
int availableActions;
|
||||||
|
int proposedAction;
|
||||||
|
int chosenAction;
|
||||||
|
} _GLFWdroptarget;
|
||||||
|
|
||||||
// Win32-specific per-window data
|
// Win32-specific per-window data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWwindowWin32
|
typedef struct _GLFWwindowWin32
|
||||||
@ -432,6 +458,8 @@ typedef struct _GLFWwindowWin32
|
|||||||
int lastCursorPosX, lastCursorPosY;
|
int lastCursorPosX, lastCursorPosY;
|
||||||
// The last received high surrogate when decoding pairs of UTF-16 messages
|
// The last received high surrogate when decoding pairs of UTF-16 messages
|
||||||
WCHAR highSurrogate;
|
WCHAR highSurrogate;
|
||||||
|
|
||||||
|
_GLFWdroptarget dropTarget;
|
||||||
} _GLFWwindowWin32;
|
} _GLFWwindowWin32;
|
||||||
|
|
||||||
// Win32-specific global data
|
// Win32-specific global data
|
||||||
@ -457,6 +485,7 @@ typedef struct _GLFWlibraryWin32
|
|||||||
RAWINPUT* rawInput;
|
RAWINPUT* rawInput;
|
||||||
int rawInputSize;
|
int rawInputSize;
|
||||||
UINT mouseTrailSize;
|
UINT mouseTrailSize;
|
||||||
|
IDropTargetVtbl dropTargetVtbl;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
HINSTANCE instance;
|
HINSTANCE instance;
|
||||||
@ -499,6 +528,15 @@ typedef struct _GLFWlibraryWin32
|
|||||||
HINSTANCE instance;
|
HINSTANCE instance;
|
||||||
PFN_RtlVerifyVersionInfo RtlVerifyVersionInfo_;
|
PFN_RtlVerifyVersionInfo RtlVerifyVersionInfo_;
|
||||||
} ntdll;
|
} ntdll;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
HINSTANCE instance;
|
||||||
|
|
||||||
|
PFN_OleInitialize OleInitialize_;
|
||||||
|
PFN_OleUninitialize OleUninitialize_;
|
||||||
|
PFN_RegisterDragDrop RegisterDragDrop_;
|
||||||
|
PFN_RevokeDragDrop RevokeDragDrop_;
|
||||||
|
} ole32;
|
||||||
} _GLFWlibraryWin32;
|
} _GLFWlibraryWin32;
|
||||||
|
|
||||||
// Win32-specific per-monitor data
|
// Win32-specific per-monitor data
|
||||||
@ -622,3 +660,11 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig);
|
const _GLFWfbconfig* fbconfig);
|
||||||
|
|
||||||
|
// IDropTarget vtable functions
|
||||||
|
//HRESULT STDMETHODCALLTYPE _glfwDropTarget_QueryInterface(IDropTarget *_This, REFIID riid, void **ppvObject);
|
||||||
|
ULONG STDMETHODCALLTYPE _glfwDropTarget_AddRef(IDropTarget *_This);
|
||||||
|
ULONG STDMETHODCALLTYPE _glfwDropTarget_Release(IDropTarget *_This);
|
||||||
|
HRESULT STDMETHODCALLTYPE _glfwDropTarget_DragEnter(IDropTarget *_This, IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
|
||||||
|
HRESULT STDMETHODCALLTYPE _glfwDropTarget_DragOver(IDropTarget *_This, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
|
||||||
|
HRESULT STDMETHODCALLTYPE _glfwDropTarget_DragLeave(IDropTarget *_This);
|
||||||
|
HRESULT STDMETHODCALLTYPE _glfwDropTarget_Drop(IDropTarget *_This, IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <stdio.h> // TODO remove
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <windowsx.h>
|
#include <windowsx.h>
|
||||||
@ -1426,7 +1427,15 @@ static int createNativeWindow(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DragAcceptFiles(window->win32.handle, TRUE);
|
//DragAcceptFiles(window->win32.handle, TRUE);
|
||||||
|
window->win32.dropTarget.lpVtbl = &_glfw.win32.dropTargetVtbl;
|
||||||
|
window->win32.dropTarget.window = window;
|
||||||
|
if (FAILED(RegisterDragDrop(window->win32.handle, (LPDROPTARGET)&window->win32.dropTarget)))
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to register window for drag & drop");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (fbconfig->transparent)
|
if (fbconfig->transparent)
|
||||||
{
|
{
|
||||||
@ -1515,6 +1524,8 @@ void _glfwDestroyWindowWin32(_GLFWwindow* window)
|
|||||||
if (_glfw.win32.capturedCursorWindow == window)
|
if (_glfw.win32.capturedCursorWindow == window)
|
||||||
releaseCursor();
|
releaseCursor();
|
||||||
|
|
||||||
|
RevokeDragDrop(window->win32.handle);
|
||||||
|
|
||||||
if (window->win32.handle)
|
if (window->win32.handle)
|
||||||
{
|
{
|
||||||
RemovePropW(window->win32.handle, L"GLFW");
|
RemovePropW(window->win32.handle, L"GLFW");
|
||||||
@ -2500,3 +2511,232 @@ GLFWAPI HWND glfwGetWin32Window(GLFWwindow* handle)
|
|||||||
return window->win32.handle;
|
return window->win32.handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*static GLFWbool _glfwIsEqualIID(REFIID riid1, REFIID riid2)
|
||||||
|
{
|
||||||
|
return riid1->Data1 == riid2->Data1
|
||||||
|
&& riid1->Data2 == riid2->Data2
|
||||||
|
&& riid1->Data3 == riid2->Data3
|
||||||
|
&& (memcmp(riid1->Data4, riid2->Data4, sizeof(riid1->Data4)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// IDropTarget vtable functions
|
||||||
|
HRESULT STDMETHODCALLTYPE _glfwDropTarget_QueryInterface(IDropTarget *_This, REFIID riid, void **ppvObject)
|
||||||
|
{
|
||||||
|
_GLFWdroptarget *This = (_GLFWdroptarget*) _This;
|
||||||
|
printf("DropTarget_QueryInterface\n");
|
||||||
|
if(!ppvObject)
|
||||||
|
return E_POINTER;
|
||||||
|
|
||||||
|
if (_glfwIsEqualIID(riid, &IID_IUnknown) || _glfwIsEqualIID(riid, &IID_IDropTarget))
|
||||||
|
{
|
||||||
|
*ppvObject = This;
|
||||||
|
This->lpVtbl->AddRef(This);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ppvObject = 0;
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// IDropTarget utility functions
|
||||||
|
static void getActions(_GLFWdroptarget *This, DWORD dwEffect)
|
||||||
|
{
|
||||||
|
This->availableActions = GLFW_DND_NONE;
|
||||||
|
This->proposedAction = GLFW_DND_NONE;
|
||||||
|
if ((dwEffect & DROPEFFECT_COPY) == DROPEFFECT_COPY)
|
||||||
|
{
|
||||||
|
This->availableActions |= GLFW_DND_COPY;
|
||||||
|
if (!This->proposedAction)
|
||||||
|
This->proposedAction = GLFW_DND_COPY;
|
||||||
|
}
|
||||||
|
if ((dwEffect & DROPEFFECT_LINK) == DROPEFFECT_LINK)
|
||||||
|
{
|
||||||
|
This->availableActions |= GLFW_DND_LINK;
|
||||||
|
if (!This->proposedAction)
|
||||||
|
This->proposedAction = GLFW_DND_LINK;
|
||||||
|
}
|
||||||
|
if ((dwEffect & DROPEFFECT_MOVE) == DROPEFFECT_MOVE)
|
||||||
|
{
|
||||||
|
This->availableActions |= GLFW_DND_MOVE;
|
||||||
|
if (!This->proposedAction)
|
||||||
|
This->proposedAction = GLFW_DND_MOVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setActions(_GLFWdroptarget *This, DWORD *pdwEffect)
|
||||||
|
{
|
||||||
|
if((This->chosenAction & GLFW_DND_COPY) == GLFW_DND_COPY)
|
||||||
|
*pdwEffect = DROPEFFECT_COPY;
|
||||||
|
else if((This->chosenAction & GLFW_DND_LINK) == GLFW_DND_LINK)
|
||||||
|
*pdwEffect = DROPEFFECT_LINK;
|
||||||
|
else if((This->chosenAction & GLFW_DND_MOVE) == GLFW_DND_MOVE)
|
||||||
|
*pdwEffect = DROPEFFECT_MOVE;
|
||||||
|
else
|
||||||
|
*pdwEffect = DROPEFFECT_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FORMATETC *withClipFormat(FORMATETC *pFmt, CLIPFORMAT cf)
|
||||||
|
{
|
||||||
|
pFmt->cfFormat = cf;
|
||||||
|
return pFmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IDropTarget vtable functions
|
||||||
|
ULONG STDMETHODCALLTYPE _glfwDropTarget_AddRef(IDropTarget *_This)
|
||||||
|
{
|
||||||
|
_GLFWdroptarget *This = (_GLFWdroptarget*) _This;
|
||||||
|
printf("DropTarget_AddRef\n");
|
||||||
|
return ++This->cRefCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE _glfwDropTarget_Release(IDropTarget *_This)
|
||||||
|
{
|
||||||
|
_GLFWdroptarget *This = (_GLFWdroptarget*) _This;
|
||||||
|
printf("DropTarget_Release\n");
|
||||||
|
return --This->cRefCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE _glfwDropTarget_DragEnter(IDropTarget *_This, IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
|
||||||
|
{
|
||||||
|
_GLFWdroptarget *This = (_GLFWdroptarget*) _This;
|
||||||
|
FORMATETC fmt = { 0, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||||
|
STGMEDIUM stgmed;
|
||||||
|
|
||||||
|
printf("DropTarget_DragEnter\n");
|
||||||
|
|
||||||
|
getActions(This, *pdwEffect);
|
||||||
|
|
||||||
|
This->availableFormats = GLFW_DND_NONE;
|
||||||
|
|
||||||
|
if (SUCCEEDED(IDataObject_QueryGetData(pDataObj, withClipFormat(&fmt, CF_HDROP)))
|
||||||
|
&& SUCCEEDED(IDataObject_GetData(pDataObj, &fmt, &stgmed)))
|
||||||
|
{
|
||||||
|
This->availableFormats |= GLFW_DND_PATHS;
|
||||||
|
printf("paths\n");
|
||||||
|
}
|
||||||
|
if (SUCCEEDED(IDataObject_QueryGetData(pDataObj, withClipFormat(&fmt, CF_TEXT)))
|
||||||
|
&& SUCCEEDED(IDataObject_GetData(pDataObj, &fmt, &stgmed)))
|
||||||
|
{
|
||||||
|
This->availableFormats |= GLFW_DND_TEXT;
|
||||||
|
printf("text\n");
|
||||||
|
ReleaseStgMedium(&stgmed);
|
||||||
|
}
|
||||||
|
|
||||||
|
This->window->dndDragging = GLFW_TRUE;
|
||||||
|
|
||||||
|
This->chosenFormat = This->availableFormats;
|
||||||
|
This->chosenAction = This->proposedAction;
|
||||||
|
_glfwInputDrag(This->window, GLFW_DND_ENTER, pt.x, pt.y,
|
||||||
|
This->availableFormats,
|
||||||
|
&This->chosenFormat,
|
||||||
|
This->availableActions,
|
||||||
|
&This->chosenAction);
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE _glfwDropTarget_DragOver(IDropTarget *_This, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
|
||||||
|
{
|
||||||
|
_GLFWdroptarget *This = (_GLFWdroptarget*) _This;
|
||||||
|
printf("DropTarget_DragOver\n");
|
||||||
|
|
||||||
|
getActions(This, *pdwEffect);
|
||||||
|
|
||||||
|
_glfwInputCursorPos(This->window, pt.x, pt.y);
|
||||||
|
|
||||||
|
This->chosenAction = This->proposedAction;
|
||||||
|
_glfwInputDrag(This->window, GLFW_DND_DRAG, pt.x, pt.y,
|
||||||
|
This->availableFormats,
|
||||||
|
&This->chosenFormat,
|
||||||
|
This->availableActions,
|
||||||
|
&This->chosenAction);
|
||||||
|
|
||||||
|
setActions(This, pdwEffect);
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE _glfwDropTarget_DragLeave(IDropTarget *_This)
|
||||||
|
{
|
||||||
|
_GLFWdroptarget *This = (_GLFWdroptarget*) _This;
|
||||||
|
printf("DropTarget_DragLeave\n");
|
||||||
|
|
||||||
|
This->window->dndDragging = GLFW_FALSE;
|
||||||
|
|
||||||
|
This->chosenFormat =
|
||||||
|
This->availableFormats = GLFW_DND_NONE;
|
||||||
|
This->chosenAction =
|
||||||
|
This->proposedAction =
|
||||||
|
This->availableActions = GLFW_DND_NONE;
|
||||||
|
_glfwInputDrag(This->window, GLFW_DND_LEAVE, 0.0, 0.0,
|
||||||
|
This->availableFormats,
|
||||||
|
&This->chosenFormat,
|
||||||
|
This->availableActions,
|
||||||
|
&This->chosenAction);
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE _glfwDropTarget_Drop(IDropTarget *_This, IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
|
||||||
|
{
|
||||||
|
_GLFWdroptarget *This = (_GLFWdroptarget*) _This;
|
||||||
|
FORMATETC fmt = { 0, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||||
|
STGMEDIUM stgmed;
|
||||||
|
|
||||||
|
printf("DropTarget_Drop\n");
|
||||||
|
*pdwEffect = DROPEFFECT_NONE;
|
||||||
|
|
||||||
|
This->window->dndDragging = GLFW_FALSE;
|
||||||
|
|
||||||
|
if ((This->chosenFormat & GLFW_DND_PATHS) == GLFW_DND_PATHS
|
||||||
|
&& SUCCEEDED(IDataObject_GetData(pDataObj, withClipFormat(&fmt, CF_HDROP), &stgmed)))
|
||||||
|
{
|
||||||
|
HDROP drop = (HDROP) GlobalLock(stgmed.hGlobal);
|
||||||
|
const int count = DragQueryFileW(drop, 0xffffffff, NULL, 0);
|
||||||
|
char** paths = _glfw_calloc(count, sizeof(char*));
|
||||||
|
int i;
|
||||||
|
|
||||||
|
printf("GetData OK (paths)\n");
|
||||||
|
_glfwInputCursorPos(This->window, pt.x, pt.y);
|
||||||
|
|
||||||
|
for (i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
const UINT length = DragQueryFileW(drop, i, NULL, 0);
|
||||||
|
WCHAR* buffer = _glfw_calloc((size_t) length + 1, sizeof(WCHAR));
|
||||||
|
|
||||||
|
DragQueryFileW(drop, i, buffer, length + 1);
|
||||||
|
paths[i] = _glfwCreateUTF8FromWideStringWin32(buffer);
|
||||||
|
|
||||||
|
_glfw_free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwInputDrop(This->window, count, (const char**) paths);
|
||||||
|
|
||||||
|
_glfwInputDropEx(This->window, GLFW_DND_PATHS, count, paths,
|
||||||
|
&This->chosenAction);
|
||||||
|
|
||||||
|
for (i = 0; i < count; ++i)
|
||||||
|
_glfw_free(paths[i]);
|
||||||
|
_glfw_free(paths);
|
||||||
|
}
|
||||||
|
else if ((This->chosenFormat & GLFW_DND_TEXT) == GLFW_DND_TEXT
|
||||||
|
&& SUCCEEDED(IDataObject_GetData(pDataObj, withClipFormat(&fmt, CF_TEXT), &stgmed)))
|
||||||
|
{
|
||||||
|
char *text = (char*) GlobalLock(stgmed.hGlobal);
|
||||||
|
|
||||||
|
printf("GetData OK (text)\n");
|
||||||
|
_glfwInputCursorPos(This->window, pt.x, pt.y);
|
||||||
|
|
||||||
|
_glfwInputDropEx(This->window, GLFW_DND_TEXT, -1, text,
|
||||||
|
&This->chosenAction);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
GlobalUnlock(stgmed.hGlobal);
|
||||||
|
ReleaseStgMedium(&stgmed);
|
||||||
|
|
||||||
|
setActions(This, pdwEffect);
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
@ -860,6 +860,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
|
|||||||
return window->focusOnShow;
|
return window->focusOnShow;
|
||||||
case GLFW_MOUSE_PASSTHROUGH:
|
case GLFW_MOUSE_PASSTHROUGH:
|
||||||
return window->mousePassthrough;
|
return window->mousePassthrough;
|
||||||
|
case GLFW_DND_DRAGGING:
|
||||||
|
return window->dndDragging;
|
||||||
case GLFW_TRANSPARENT_FRAMEBUFFER:
|
case GLFW_TRANSPARENT_FRAMEBUFFER:
|
||||||
return _glfw.platform.framebufferTransparent(window);
|
return _glfw.platform.framebufferTransparent(window);
|
||||||
case GLFW_RESIZABLE:
|
case GLFW_RESIZABLE:
|
||||||
|
@ -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
@ -1534,15 +1534,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,
|
||||||
@ -1556,27 +1563,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];
|
||||||
@ -1584,7 +1639,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);
|
||||||
@ -1609,12 +1664,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,
|
||||||
@ -1624,6 +1696,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;
|
||||||
@ -1632,12 +1711,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,
|
||||||
@ -1661,15 +1747,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)
|
||||||
@ -1683,7 +1793,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