mirror of
https://github.com/glfw/glfw.git
synced 2024-12-02 06:47:10 +00:00
Win32: Implement extended drag & drop API
This commit is contained in:
parent
d2763ec2a1
commit
2933c00e54
@ -458,12 +458,12 @@ static GLFWbool initDragDrop()
|
||||
}
|
||||
|
||||
//_glfw.win32.dropTargetVtbl.QueryInterface = _glfwDropTarget_QueryInterface;
|
||||
_glfw.win32.dropTargetVtbl.AddRef = (PFN_IDropTarget_AddRef)_glfwDropTarget_AddRef;
|
||||
_glfw.win32.dropTargetVtbl.Release = (PFN_IDropTarget_Release)_glfwDropTarget_Release;
|
||||
_glfw.win32.dropTargetVtbl.DragEnter = (PFN_IDropTarget_DragEnter)_glfwDropTarget_DragEnter;
|
||||
_glfw.win32.dropTargetVtbl.DragOver = (PFN_IDropTarget_DragOver)_glfwDropTarget_DragOver;
|
||||
_glfw.win32.dropTargetVtbl.DragLeave = (PFN_IDropTarget_DragLeave)_glfwDropTarget_DragLeave;
|
||||
_glfw.win32.dropTargetVtbl.Drop = (PFN_IDropTarget_Drop)_glfwDropTarget_Drop;
|
||||
_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;
|
||||
}
|
||||
|
@ -325,12 +325,6 @@ 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);
|
||||
typedef ULONG (STDMETHODCALLTYPE * PFN_IDropTarget_AddRef)(LPDROPTARGET);
|
||||
typedef ULONG (STDMETHODCALLTYPE * PFN_IDropTarget_Release)(LPDROPTARGET);
|
||||
typedef HRESULT (STDMETHODCALLTYPE * PFN_IDropTarget_DragEnter)(LPDROPTARGET,IDataObject*,DWORD,POINTL,DWORD*);
|
||||
typedef HRESULT (STDMETHODCALLTYPE * PFN_IDropTarget_DragOver)(LPDROPTARGET,DWORD,POINTL,DWORD*);
|
||||
typedef HRESULT (STDMETHODCALLTYPE * PFN_IDropTarget_DragLeave)(LPDROPTARGET);
|
||||
typedef HRESULT (STDMETHODCALLTYPE * PFN_IDropTarget_Drop)(LPDROPTARGET,IDataObject*,DWORD,POINTL,DWORD*);
|
||||
#define OleInitialize _glfw.win32.ole32.OleInitialize_
|
||||
#define OleUninitialize _glfw.win32.ole32.OleUninitialize_
|
||||
#define RegisterDragDrop _glfw.win32.ole32.RegisterDragDrop_
|
||||
@ -428,12 +422,17 @@ typedef struct _GLFWlibraryWGL
|
||||
GLFWbool ARB_context_flush_control;
|
||||
} _GLFWlibraryWGL;
|
||||
|
||||
typedef struct _GLFWdropTarget
|
||||
typedef struct _GLFWdroptarget
|
||||
{
|
||||
IDropTargetVtbl* lpVtbl;
|
||||
ULONG cRefCount;
|
||||
_GLFWwindow* window;
|
||||
} _GLFWdropTarget;
|
||||
int availableFormats;
|
||||
int chosenFormat;
|
||||
int availableActions;
|
||||
int proposedAction;
|
||||
int chosenAction;
|
||||
} _GLFWdroptarget;
|
||||
|
||||
// Win32-specific per-window data
|
||||
//
|
||||
@ -460,7 +459,7 @@ typedef struct _GLFWwindowWin32
|
||||
// The last received high surrogate when decoding pairs of UTF-16 messages
|
||||
WCHAR highSurrogate;
|
||||
|
||||
_GLFWdropTarget dropTarget;
|
||||
_GLFWdroptarget dropTarget;
|
||||
} _GLFWwindowWin32;
|
||||
|
||||
// Win32-specific global data
|
||||
@ -660,10 +659,10 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
const _GLFWfbconfig* fbconfig);
|
||||
|
||||
// IDropTarget vtable functions
|
||||
//HRESULT STDMETHODCALLTYPE _glfwDropTarget_QueryInterface(_GLFWdropTarget *This, REFIID riid, void **ppvObject);
|
||||
ULONG STDMETHODCALLTYPE _glfwDropTarget_AddRef(_GLFWdropTarget *This);
|
||||
ULONG STDMETHODCALLTYPE _glfwDropTarget_Release(_GLFWdropTarget *This);
|
||||
HRESULT STDMETHODCALLTYPE _glfwDropTarget_DragEnter(_GLFWdropTarget *This, IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
|
||||
HRESULT STDMETHODCALLTYPE _glfwDropTarget_DragOver(_GLFWdropTarget *This, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
|
||||
HRESULT STDMETHODCALLTYPE _glfwDropTarget_DragLeave(_GLFWdropTarget *This);
|
||||
HRESULT STDMETHODCALLTYPE _glfwDropTarget_Drop(_GLFWdropTarget *This, IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
|
||||
//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);
|
||||
|
@ -2472,8 +2472,9 @@ GLFWAPI HWND glfwGetWin32Window(GLFWwindow* handle)
|
||||
}
|
||||
|
||||
// IDropTarget vtable functions
|
||||
HRESULT STDMETHODCALLTYPE _glfwDropTarget_QueryInterface(_GLFWdropTarget *This, REFIID riid, void **ppvObject)
|
||||
HRESULT STDMETHODCALLTYPE _glfwDropTarget_QueryInterface(IDropTarget *_This, REFIID riid, void **ppvObject)
|
||||
{
|
||||
_GLFWdroptarget *This = (_GLFWdroptarget*) _This;
|
||||
printf("DropTarget_QueryInterface\n");
|
||||
if(!ppvObject)
|
||||
return E_POINTER;
|
||||
@ -2489,93 +2490,205 @@ HRESULT STDMETHODCALLTYPE _glfwDropTarget_QueryInterface(_GLFWdropTarget *This,
|
||||
return E_NOINTERFACE;
|
||||
}*/
|
||||
|
||||
// IDropTarget vtable functions
|
||||
ULONG STDMETHODCALLTYPE _glfwDropTarget_AddRef(_GLFWdropTarget *This)
|
||||
// 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(_GLFWdropTarget *This)
|
||||
ULONG STDMETHODCALLTYPE _glfwDropTarget_Release(IDropTarget *_This)
|
||||
{
|
||||
_GLFWdroptarget *This = (_GLFWdroptarget*) _This;
|
||||
printf("DropTarget_Release\n");
|
||||
return --This->cRefCount;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE _glfwDropTarget_DragEnter(_GLFWdropTarget *This, IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
|
||||
HRESULT STDMETHODCALLTYPE _glfwDropTarget_DragEnter(IDropTarget *_This, IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
|
||||
{
|
||||
FORMATETC fmt = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||
_GLFWdroptarget *This = (_GLFWdroptarget*) _This;
|
||||
FORMATETC fmt = { 0, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||
STGMEDIUM stgmed;
|
||||
|
||||
printf("DropTarget_DragEnter\n");
|
||||
if(SUCCEEDED(IDataObject_QueryGetData(pDataObj, &fmt)))
|
||||
|
||||
getActions(This, *pdwEffect);
|
||||
|
||||
This->availableFormats = GLFW_DND_NONE;
|
||||
|
||||
if (SUCCEEDED(IDataObject_QueryGetData(pDataObj, withClipFormat(&fmt, CF_HDROP)))
|
||||
&& SUCCEEDED(IDataObject_GetData(pDataObj, &fmt, &stgmed)))
|
||||
{
|
||||
printf("QueryGetData OK\n");
|
||||
*pdwEffect = DROPEFFECT_COPY;
|
||||
This->availableFormats |= GLFW_DND_PATHS;
|
||||
printf("paths\n");
|
||||
}
|
||||
else
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
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(_GLFWdropTarget *This, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
|
||||
HRESULT STDMETHODCALLTYPE _glfwDropTarget_DragOver(IDropTarget *_This, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
|
||||
{
|
||||
_GLFWdroptarget *This = (_GLFWdroptarget*) _This;
|
||||
printf("DropTarget_DragOver\n");
|
||||
*pdwEffect = DROPEFFECT_COPY;
|
||||
|
||||
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(_GLFWdropTarget *This)
|
||||
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(_GLFWdropTarget *This, IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
|
||||
HRESULT STDMETHODCALLTYPE _glfwDropTarget_Drop(IDropTarget *_This, IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
|
||||
{
|
||||
FORMATETC fmt = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||
_GLFWdroptarget *This = (_GLFWdroptarget*) _This;
|
||||
FORMATETC fmt = { 0, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||
STGMEDIUM stgmed;
|
||||
|
||||
printf("DropTarget_Drop\n");
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
|
||||
if(SUCCEEDED(IDataObject_QueryGetData(pDataObj, &fmt)))
|
||||
{
|
||||
printf("QueryGetData OK\n");
|
||||
if(SUCCEEDED(IDataObject_GetData(pDataObj, &fmt, &stgmed)))
|
||||
{
|
||||
HDROP drop = (HDROP) GlobalLock(stgmed.hGlobal);
|
||||
const int count = DragQueryFileW(drop, 0xffffffff, NULL, 0);
|
||||
char** paths = _glfw_calloc(count, sizeof(char*));
|
||||
int i;
|
||||
This->window->dndDragging = GLFW_FALSE;
|
||||
|
||||
printf("GetData OK\n");
|
||||
_glfwInputCursorPos(This->window, pt.x, pt.y);
|
||||
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;
|
||||
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
const UINT length = DragQueryFileW(drop, i, NULL, 0);
|
||||
WCHAR* buffer = _glfw_calloc((size_t) length + 1, sizeof(WCHAR));
|
||||
printf("GetData OK (paths)\n");
|
||||
_glfwInputCursorPos(This->window, pt.x, pt.y);
|
||||
|
||||
DragQueryFileW(drop, i, buffer, length + 1);
|
||||
paths[i] = _glfwCreateUTF8FromWideStringWin32(buffer);
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
const UINT length = DragQueryFileW(drop, i, NULL, 0);
|
||||
WCHAR* buffer = _glfw_calloc((size_t) length + 1, sizeof(WCHAR));
|
||||
|
||||
_glfw_free(buffer);
|
||||
}
|
||||
DragQueryFileW(drop, i, buffer, length + 1);
|
||||
paths[i] = _glfwCreateUTF8FromWideStringWin32(buffer);
|
||||
|
||||
_glfwInputDrop(This->window, count, (const char**) paths);
|
||||
_glfw_free(buffer);
|
||||
}
|
||||
|
||||
for (i = 0; i < count; ++i)
|
||||
_glfw_free(paths[i]);
|
||||
_glfw_free(paths);
|
||||
_glfwInputDrop(This->window, count, (const char**) paths);
|
||||
|
||||
GlobalUnlock(stgmed.hGlobal);
|
||||
ReleaseStgMedium(&stgmed);
|
||||
_glfwInputDropEx(This->window, GLFW_DND_PATHS, count, paths,
|
||||
&This->chosenAction);
|
||||
|
||||
*pdwEffect = DROPEFFECT_COPY;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user