|
@@ -24,12 +24,13 @@
|
|
|
|
|
|
#include "../../core/windows/SDL_windows.h"
|
|
|
|
|
|
-#include "../SDL_sysvideo.h"
|
|
|
-#include "../SDL_pixels_c.h"
|
|
|
+#include "../../SDL_hints_c.h"
|
|
|
+#include "../../events/SDL_dropevents_c.h"
|
|
|
#include "../../events/SDL_keyboard_c.h"
|
|
|
#include "../../events/SDL_mouse_c.h"
|
|
|
#include "../../events/SDL_windowevents_c.h"
|
|
|
-#include "../../SDL_hints_c.h"
|
|
|
+#include "../SDL_pixels_c.h"
|
|
|
+#include "../SDL_sysvideo.h"
|
|
|
|
|
|
#include "SDL_windowsvideo.h"
|
|
|
#include "SDL_windowswindow.h"
|
|
@@ -188,26 +189,27 @@ static int WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, DWORD
|
|
|
|
|
|
/* Client rect, in points */
|
|
|
switch (rect_type) {
|
|
|
- case SDL_WINDOWRECT_CURRENT:
|
|
|
- SDL_RelativeToGlobalForWindow(window, window->x, window->y, x, y);
|
|
|
- *width = window->w;
|
|
|
- *height = window->h;
|
|
|
- break;
|
|
|
- case SDL_WINDOWRECT_WINDOWED:
|
|
|
- SDL_RelativeToGlobalForWindow(window, window->windowed.x, window->windowed.y, x, y);
|
|
|
- *width = window->windowed.w;
|
|
|
- *height = window->windowed.h;
|
|
|
- break;
|
|
|
- case SDL_WINDOWRECT_FLOATING:
|
|
|
- SDL_RelativeToGlobalForWindow(window, window->floating.x, window->floating.y, x, y);
|
|
|
- *width = window->floating.w;
|
|
|
- *height = window->floating.h;
|
|
|
- break;
|
|
|
- default:
|
|
|
- /* Should never be here */
|
|
|
- SDL_assert_release(SDL_FALSE);
|
|
|
- *width = 0;
|
|
|
- *height = 0;
|
|
|
+ case SDL_WINDOWRECT_CURRENT:
|
|
|
+ SDL_RelativeToGlobalForWindow(window, window->x, window->y, x, y);
|
|
|
+ *width = window->w;
|
|
|
+ *height = window->h;
|
|
|
+ break;
|
|
|
+ case SDL_WINDOWRECT_WINDOWED:
|
|
|
+ SDL_RelativeToGlobalForWindow(window, window->windowed.x, window->windowed.y, x, y);
|
|
|
+ *width = window->windowed.w;
|
|
|
+ *height = window->windowed.h;
|
|
|
+ break;
|
|
|
+ case SDL_WINDOWRECT_FLOATING:
|
|
|
+ SDL_RelativeToGlobalForWindow(window, window->floating.x, window->floating.y, x, y);
|
|
|
+ *width = window->floating.w;
|
|
|
+ *height = window->floating.h;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ /* Should never be here */
|
|
|
+ SDL_assert_release(SDL_FALSE);
|
|
|
+ *width = 0;
|
|
|
+ *height = 0;
|
|
|
+ break;
|
|
|
}
|
|
|
|
|
|
/* Copy the client size in pixels into this rect structure,
|
|
@@ -587,6 +589,10 @@ static void CleanupWindowData(SDL_VideoDevice *_this, SDL_Window *window)
|
|
|
if (data) {
|
|
|
SDL_DelHintCallback(SDL_HINT_MOUSE_RELATIVE_MODE_CENTER, WIN_MouseRelativeModeCenterChanged, data);
|
|
|
|
|
|
+ if (data->drop_target) {
|
|
|
+ WIN_AcceptDragAndDrop(window, SDL_FALSE);
|
|
|
+ }
|
|
|
+
|
|
|
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
|
|
if (data->ICMFileName) {
|
|
|
SDL_free(data->ICMFileName);
|
|
@@ -1136,7 +1142,7 @@ void WIN_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
|
|
SetWindowPos(hwnd, HWND_TOP, fx, fy, fw, fh, data->copybits_flag | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOACTIVATE);
|
|
|
data->expected_resize = SDL_FALSE;
|
|
|
}
|
|
|
- }else {
|
|
|
+ } else {
|
|
|
data->windowed_mode_was_maximized = SDL_TRUE;
|
|
|
}
|
|
|
}
|
|
@@ -1693,10 +1699,468 @@ int WIN_SetWindowOpacity(SDL_VideoDevice *_this, SDL_Window *window, float opaci
|
|
|
}
|
|
|
|
|
|
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
|
|
+
|
|
|
+static const char *SDLGetClipboardFormatName(UINT cf, char *text, int len)
|
|
|
+{
|
|
|
+ switch (cf) {
|
|
|
+ case CF_TEXT:
|
|
|
+ return "CF_TEXT";
|
|
|
+ case CF_BITMAP:
|
|
|
+ return "CF_BITMAP";
|
|
|
+ case CF_METAFILEPICT:
|
|
|
+ return "CF_METAFILEPICT";
|
|
|
+ case CF_SYLK:
|
|
|
+ return "CF_SYLK";
|
|
|
+ case CF_DIF:
|
|
|
+ return "CF_DIF";
|
|
|
+ case CF_TIFF:
|
|
|
+ return "CF_TIFF";
|
|
|
+ case CF_OEMTEXT:
|
|
|
+ return "CF_OEMTEXT";
|
|
|
+ case CF_DIB:
|
|
|
+ return "CF_DIB";
|
|
|
+ case CF_PALETTE:
|
|
|
+ return "CF_PALETTE";
|
|
|
+ case CF_PENDATA:
|
|
|
+ return "CF_PENDATA";
|
|
|
+ case CF_RIFF:
|
|
|
+ return "CF_RIFF";
|
|
|
+ case CF_WAVE:
|
|
|
+ return "CF_WAVE";
|
|
|
+ case CF_UNICODETEXT:
|
|
|
+ return "CF_UNICODETEXT";
|
|
|
+ case CF_ENHMETAFILE:
|
|
|
+ return "CF_ENHMETAFILE";
|
|
|
+ case CF_HDROP:
|
|
|
+ return "CF_HDROP";
|
|
|
+ case CF_LOCALE:
|
|
|
+ return "CF_LOCALE";
|
|
|
+ case CF_DIBV5:
|
|
|
+ return "CF_DIBV5";
|
|
|
+ case CF_OWNERDISPLAY:
|
|
|
+ return "CF_OWNERDISPLAY";
|
|
|
+ case CF_DSPTEXT:
|
|
|
+ return "CF_DSPTEXT";
|
|
|
+ case CF_DSPBITMAP:
|
|
|
+ return "CF_DSPBITMAP";
|
|
|
+ case CF_DSPMETAFILEPICT:
|
|
|
+ return "CF_DSPMETAFILEPICT";
|
|
|
+ case CF_DSPENHMETAFILE:
|
|
|
+ return "CF_DSPENHMETAFILE";
|
|
|
+ default:
|
|
|
+ if (GetClipboardFormatNameA(cf, text, len)) {
|
|
|
+ return text;
|
|
|
+ } else {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static STDMETHODIMP_(ULONG) SDLDropTarget_AddRef(SDLDropTarget *target)
|
|
|
+{
|
|
|
+ return ++target->refcount;
|
|
|
+}
|
|
|
+
|
|
|
+static STDMETHODIMP_(ULONG) SDLDropTarget_Release(SDLDropTarget *target)
|
|
|
+{
|
|
|
+ --target->refcount;
|
|
|
+ if (target->refcount == 0) {
|
|
|
+ SDL_free(target);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ return target->refcount;
|
|
|
+}
|
|
|
+
|
|
|
+static STDMETHODIMP SDLDropTarget_QueryInterface(SDLDropTarget *target, REFIID riid, PVOID *ppv)
|
|
|
+{
|
|
|
+ if (ppv == NULL) {
|
|
|
+ return E_INVALIDARG;
|
|
|
+ }
|
|
|
+
|
|
|
+ *ppv = NULL;
|
|
|
+ if (WIN_IsEqualIID(riid, &IID_IUnknown) ||
|
|
|
+ WIN_IsEqualIID(riid, &IID_IDropTarget)) {
|
|
|
+ *ppv = (void *)target;
|
|
|
+ }
|
|
|
+ if (*ppv) {
|
|
|
+ SDLDropTarget_AddRef(target);
|
|
|
+ return S_OK;
|
|
|
+ }
|
|
|
+ return E_NOINTERFACE;
|
|
|
+}
|
|
|
+
|
|
|
+static STDMETHODIMP SDLDropTarget_DragEnter(SDLDropTarget *target,
|
|
|
+ IDataObject *pDataObject, DWORD grfKeyState,
|
|
|
+ POINTL pt, DWORD *pdwEffect)
|
|
|
+{
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In DragEnter at %ld, %ld\n", pt.x, pt.y);
|
|
|
+ *pdwEffect = DROPEFFECT_COPY;
|
|
|
+ POINT pnt = { pt.x, pt.y };
|
|
|
+ if (ScreenToClient(target->hwnd, &pnt)) {
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In DragEnter at %ld, %ld => window %u at %ld, %ld\n", pt.x, pt.y, target->window->id, pnt.x, pnt.y);
|
|
|
+ SDL_SendDropPosition(target->window, pnt.x, pnt.y);
|
|
|
+ } else {
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In DragEnter at %ld, %ld => nil, nil\n", pt.x, pt.y);
|
|
|
+ }
|
|
|
+ return S_OK;
|
|
|
+}
|
|
|
+
|
|
|
+static STDMETHODIMP SDLDropTarget_DragOver(SDLDropTarget *target,
|
|
|
+ DWORD grfKeyState,
|
|
|
+ POINTL pt, DWORD *pdwEffect)
|
|
|
+{
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In DragOver at %ld, %ld\n", pt.x, pt.y);
|
|
|
+ *pdwEffect = DROPEFFECT_COPY;
|
|
|
+ POINT pnt = { pt.x, pt.y };
|
|
|
+ if (ScreenToClient(target->hwnd, &pnt)) {
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In DragOver at %ld, %ld => window %u at %ld, %ld\n", pt.x, pt.y, target->window->id, pnt.x, pnt.y);
|
|
|
+ SDL_SendDropPosition(target->window, pnt.x, pnt.y);
|
|
|
+ } else {
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In DragOver at %ld, %ld => nil, nil\n", pt.x, pt.y);
|
|
|
+ }
|
|
|
+ return S_OK;
|
|
|
+}
|
|
|
+
|
|
|
+static STDMETHODIMP SDLDropTarget_DragLeave(SDLDropTarget *target)
|
|
|
+{
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In DragLeave\n");
|
|
|
+ SDL_SendDropComplete(target->window);
|
|
|
+ return S_OK;
|
|
|
+}
|
|
|
+
|
|
|
+static STDMETHODIMP SDLDropTarget_Drop(SDLDropTarget *target,
|
|
|
+ IDataObject *pDataObject, DWORD grfKeyState,
|
|
|
+ POINTL pt, DWORD *pdwEffect)
|
|
|
+{
|
|
|
+ *pdwEffect = DROPEFFECT_COPY;
|
|
|
+ POINT pnt = { pt.x, pt.y };
|
|
|
+ if (ScreenToClient(target->hwnd, &pnt)) {
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop at %ld, %ld => window %u at %ld, %ld\n", pt.x, pt.y, target->window->id, pnt.x, pnt.y);
|
|
|
+ SDL_SendDropPosition(target->window, pnt.x, pnt.y);
|
|
|
+ } else {
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop at %ld, %ld => nil, nil\n", pt.x, pt.y);
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ IEnumFORMATETC *pEnumFormatEtc;
|
|
|
+ HRESULT hres;
|
|
|
+ hres = pDataObject->lpVtbl->EnumFormatEtc(pDataObject, DATADIR_GET, &pEnumFormatEtc);
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop for EnumFormatEtc, HRESULT is %08lx\n", hres);
|
|
|
+ if (hres == S_OK) {
|
|
|
+ FORMATETC fetc;
|
|
|
+ while (pEnumFormatEtc->lpVtbl->Next(pEnumFormatEtc, 1, &fetc, NULL) == S_OK) {
|
|
|
+ char name[257] = { 0 };
|
|
|
+ const char *cfnm = SDLGetClipboardFormatName(fetc.cfFormat, name, 256);
|
|
|
+ if (cfnm) {
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop, Supported format is %08x, '%s'\n", fetc.cfFormat, cfnm);
|
|
|
+ } else {
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop, Supported format is %08x, Predefined\n", fetc.cfFormat);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ FORMATETC fetc;
|
|
|
+ fetc.cfFormat = target->format_file;
|
|
|
+ fetc.ptd = NULL;
|
|
|
+ fetc.dwAspect = DVASPECT_CONTENT;
|
|
|
+ fetc.lindex = -1;
|
|
|
+ fetc.tymed = TYMED_HGLOBAL;
|
|
|
+ const char *format_mime = "text/uri-list";
|
|
|
+ if (SUCCEEDED(pDataObject->lpVtbl->QueryGetData(pDataObject, &fetc))) {
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop File for QueryGetData, format %08x '%s', success\n",
|
|
|
+ fetc.cfFormat, format_mime);
|
|
|
+ STGMEDIUM med;
|
|
|
+ HRESULT hres = pDataObject->lpVtbl->GetData(pDataObject, &fetc, &med);
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop File for GetData, format %08x '%s', HRESULT is %08lx\n",
|
|
|
+ fetc.cfFormat, format_mime, hres);
|
|
|
+ if (SUCCEEDED(hres)) {
|
|
|
+ const size_t bsize = GlobalSize(med.hGlobal);
|
|
|
+ const void *buffer = (void *)GlobalLock(med.hGlobal);
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop File for GlobalLock, format %08x '%s', memory (%lu) %p\n",
|
|
|
+ fetc.cfFormat, format_mime, (unsigned long)bsize, buffer);
|
|
|
+ if (buffer) {
|
|
|
+ char *text = SDL_malloc(bsize + sizeof(Uint32));
|
|
|
+ SDL_memcpy((Uint8 *)text, buffer, bsize);
|
|
|
+ SDL_memset((Uint8 *)text + bsize, 0, sizeof(Uint32));
|
|
|
+ char *saveptr = NULL;
|
|
|
+ char *token = SDL_strtok_r(text, "\r\n", &saveptr);
|
|
|
+ while (token != NULL) {
|
|
|
+ if (SDL_URIToLocal(token, token) >= 0) {
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop File, file (%lu of %lu) '%s'\n",
|
|
|
+ (unsigned long)strlen(token), (unsigned long)bsize, token);
|
|
|
+ SDL_SendDropFile(target->window, NULL, token);
|
|
|
+ }
|
|
|
+ token = SDL_strtok_r(NULL, "\r\n", &saveptr);
|
|
|
+ }
|
|
|
+ SDL_free(text);
|
|
|
+ }
|
|
|
+ GlobalUnlock(med.hGlobal);
|
|
|
+ ReleaseStgMedium(&med);
|
|
|
+ SDL_SendDropComplete(target->window);
|
|
|
+ return S_OK;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ FORMATETC fetc;
|
|
|
+ fetc.cfFormat = target->format_text;
|
|
|
+ fetc.ptd = NULL;
|
|
|
+ fetc.dwAspect = DVASPECT_CONTENT;
|
|
|
+ fetc.lindex = -1;
|
|
|
+ fetc.tymed = TYMED_HGLOBAL;
|
|
|
+ const char *format_mime = "text/plain;charset=utf-8";
|
|
|
+ if (SUCCEEDED(pDataObject->lpVtbl->QueryGetData(pDataObject, &fetc))) {
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop Text for QueryGetData, format %08x '%s', success\n",
|
|
|
+ fetc.cfFormat, format_mime);
|
|
|
+ STGMEDIUM med;
|
|
|
+ HRESULT hres = pDataObject->lpVtbl->GetData(pDataObject, &fetc, &med);
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop Text for GetData, format %08x '%s', HRESULT is %08lx\n",
|
|
|
+ fetc.cfFormat, format_mime, hres);
|
|
|
+ if (SUCCEEDED(hres)) {
|
|
|
+ const size_t bsize = GlobalSize(med.hGlobal);
|
|
|
+ const void *buffer = (void *)GlobalLock(med.hGlobal);
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop Text for GlobalLock, format %08x '%s', memory (%lu) %p\n",
|
|
|
+ fetc.cfFormat, format_mime, (unsigned long)bsize, buffer);
|
|
|
+ if (buffer) {
|
|
|
+ char *text = SDL_malloc(bsize + sizeof(Uint32));
|
|
|
+ SDL_memcpy((Uint8 *)text, buffer, bsize);
|
|
|
+ SDL_memset((Uint8 *)text + bsize, 0, sizeof(Uint32));
|
|
|
+ char *saveptr = NULL;
|
|
|
+ char *token = SDL_strtok_r(text, "\r\n", &saveptr);
|
|
|
+ while (token != NULL) {
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop Text, text (%lu of %lu) '%s'\n",
|
|
|
+ (unsigned long)strlen(token), (unsigned long)bsize, token);
|
|
|
+ SDL_SendDropText(target->window, (char *)token);
|
|
|
+ token = SDL_strtok_r(NULL, "\r\n", &saveptr);
|
|
|
+ }
|
|
|
+ SDL_free(text);
|
|
|
+ }
|
|
|
+ GlobalUnlock(med.hGlobal);
|
|
|
+ ReleaseStgMedium(&med);
|
|
|
+ SDL_SendDropComplete(target->window);
|
|
|
+ return S_OK;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ FORMATETC fetc;
|
|
|
+ fetc.cfFormat = CF_UNICODETEXT;
|
|
|
+ fetc.ptd = NULL;
|
|
|
+ fetc.dwAspect = DVASPECT_CONTENT;
|
|
|
+ fetc.lindex = -1;
|
|
|
+ fetc.tymed = TYMED_HGLOBAL;
|
|
|
+ const char *format_mime = "CF_UNICODETEXT";
|
|
|
+ if (SUCCEEDED(pDataObject->lpVtbl->QueryGetData(pDataObject, &fetc))) {
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop Text for QueryGetData, format %08x '%s', success\n",
|
|
|
+ fetc.cfFormat, format_mime);
|
|
|
+ STGMEDIUM med;
|
|
|
+ HRESULT hres = pDataObject->lpVtbl->GetData(pDataObject, &fetc, &med);
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop Text for GetData, format %08x '%s', HRESULT is %08lx\n",
|
|
|
+ fetc.cfFormat, format_mime, hres);
|
|
|
+ if (SUCCEEDED(hres)) {
|
|
|
+ const size_t bsize = GlobalSize(med.hGlobal);
|
|
|
+ const void *buffer = (void *)GlobalLock(med.hGlobal);
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop Text for GlobalLock, format %08x '%s', memory (%lu) %p\n",
|
|
|
+ fetc.cfFormat, format_mime, (unsigned long)bsize, buffer);
|
|
|
+ if (buffer) {
|
|
|
+ buffer = WIN_StringToUTF8(buffer);
|
|
|
+ if (buffer) {
|
|
|
+ const size_t lbuffer = strlen(buffer);
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop Text for StringToUTF8, format %08x '%s', memory (%lu) %p\n",
|
|
|
+ fetc.cfFormat, format_mime, (unsigned long)lbuffer, buffer);
|
|
|
+ char *text = SDL_malloc(lbuffer + sizeof(Uint32));
|
|
|
+ SDL_memcpy((Uint8 *)text, buffer, lbuffer);
|
|
|
+ SDL_memset((Uint8 *)text + lbuffer, 0, sizeof(Uint32));
|
|
|
+ char *saveptr = NULL;
|
|
|
+ char *token = SDL_strtok_r(text, "\r\n", &saveptr);
|
|
|
+ while (token != NULL) {
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop Text, text (%lu of %lu) '%s'\n",
|
|
|
+ (unsigned long)strlen(token), (unsigned long)lbuffer, token);
|
|
|
+ SDL_SendDropText(target->window, (char *)token);
|
|
|
+ token = SDL_strtok_r(NULL, "\r\n", &saveptr);
|
|
|
+ }
|
|
|
+ SDL_free(text);
|
|
|
+ SDL_free((void *)buffer);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ GlobalUnlock(med.hGlobal);
|
|
|
+ ReleaseStgMedium(&med);
|
|
|
+ SDL_SendDropComplete(target->window);
|
|
|
+ return S_OK;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ FORMATETC fetc;
|
|
|
+ fetc.cfFormat = CF_TEXT;
|
|
|
+ fetc.ptd = NULL;
|
|
|
+ fetc.dwAspect = DVASPECT_CONTENT;
|
|
|
+ fetc.lindex = -1;
|
|
|
+ fetc.tymed = TYMED_HGLOBAL;
|
|
|
+ const char *format_mime = "CF_TEXT";
|
|
|
+ if (SUCCEEDED(pDataObject->lpVtbl->QueryGetData(pDataObject, &fetc))) {
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop Text for QueryGetData, format %08x '%s', success\n",
|
|
|
+ fetc.cfFormat, format_mime);
|
|
|
+ STGMEDIUM med;
|
|
|
+ HRESULT hres = pDataObject->lpVtbl->GetData(pDataObject, &fetc, &med);
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop Text for GetData, format %08x '%s', HRESULT is %08lx\n",
|
|
|
+ fetc.cfFormat, format_mime, hres);
|
|
|
+ if (SUCCEEDED(hres)) {
|
|
|
+ const size_t bsize = GlobalSize(med.hGlobal);
|
|
|
+ const void *buffer = (void *)GlobalLock(med.hGlobal);
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop Text for GlobalLock, format %08x '%s', memory (%lu) %p\n",
|
|
|
+ fetc.cfFormat, format_mime, (unsigned long)bsize, buffer);
|
|
|
+ if (buffer) {
|
|
|
+ char *text = SDL_malloc(bsize + sizeof(Uint32));
|
|
|
+ SDL_memcpy((Uint8 *)text, buffer, bsize);
|
|
|
+ SDL_memset((Uint8 *)text + bsize, 0, sizeof(Uint32));
|
|
|
+ char *saveptr = NULL;
|
|
|
+ char *token = SDL_strtok_r(text, "\r\n", &saveptr);
|
|
|
+ while (token != NULL) {
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop Text, text (%lu of %lu) '%s'\n",
|
|
|
+ (unsigned long)strlen(token), (unsigned long)bsize, token);
|
|
|
+ SDL_SendDropText(target->window, (char *)token);
|
|
|
+ token = SDL_strtok_r(NULL, "\r\n", &saveptr);
|
|
|
+ }
|
|
|
+ SDL_free(text);
|
|
|
+ }
|
|
|
+ GlobalUnlock(med.hGlobal);
|
|
|
+ ReleaseStgMedium(&med);
|
|
|
+ SDL_SendDropComplete(target->window);
|
|
|
+ return S_OK;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ FORMATETC fetc;
|
|
|
+ fetc.cfFormat = CF_HDROP;
|
|
|
+ fetc.ptd = NULL;
|
|
|
+ fetc.dwAspect = DVASPECT_CONTENT;
|
|
|
+ fetc.lindex = -1;
|
|
|
+ fetc.tymed = TYMED_HGLOBAL;
|
|
|
+ const char *format_mime = "CF_HDROP";
|
|
|
+ if (SUCCEEDED(pDataObject->lpVtbl->QueryGetData(pDataObject, &fetc))) {
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop File for QueryGetData, format %08x '%s', success\n",
|
|
|
+ fetc.cfFormat, format_mime);
|
|
|
+ STGMEDIUM med;
|
|
|
+ HRESULT hres = pDataObject->lpVtbl->GetData(pDataObject, &fetc, &med);
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop File for GetData, format %08x '%s', HRESULT is %08lx\n",
|
|
|
+ fetc.cfFormat, format_mime, hres);
|
|
|
+ if (SUCCEEDED(hres)) {
|
|
|
+ const size_t bsize = GlobalSize(med.hGlobal);
|
|
|
+ HDROP drop = (HDROP)GlobalLock(med.hGlobal);
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop File for GlobalLock, format %08x '%s', memory (%lu) %p\n",
|
|
|
+ fetc.cfFormat, format_mime, (unsigned long)bsize, drop);
|
|
|
+ UINT count = DragQueryFile(drop, 0xFFFFFFFF, NULL, 0);
|
|
|
+ for (UINT i = 0; i < count; ++i) {
|
|
|
+ SDL_bool isstack;
|
|
|
+ UINT size = DragQueryFile(drop, i, NULL, 0) + 1;
|
|
|
+ LPTSTR buffer = SDL_small_alloc(TCHAR, size, &isstack);
|
|
|
+ if (buffer) {
|
|
|
+ if (DragQueryFile(drop, i, buffer, size)) {
|
|
|
+ char *file = WIN_StringToUTF8(buffer);
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Drop File, file (%lu of %lu) '%s'\n",
|
|
|
+ (unsigned long)strlen(file), (unsigned long)bsize, file);
|
|
|
+ SDL_SendDropFile(target->window, NULL, file);
|
|
|
+ SDL_free(file);
|
|
|
+ }
|
|
|
+ SDL_small_free(buffer, isstack);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ GlobalUnlock(med.hGlobal);
|
|
|
+ ReleaseStgMedium(&med);
|
|
|
+ SDL_SendDropComplete(target->window);
|
|
|
+ return S_OK;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ SDL_SendDropComplete(target->window);
|
|
|
+ return S_OK;
|
|
|
+}
|
|
|
+
|
|
|
+static void *vtDropTarget[] = {
|
|
|
+ (void *)(SDLDropTarget_QueryInterface),
|
|
|
+ (void *)(SDLDropTarget_AddRef),
|
|
|
+ (void *)(SDLDropTarget_Release),
|
|
|
+ (void *)(SDLDropTarget_DragEnter),
|
|
|
+ (void *)(SDLDropTarget_DragOver),
|
|
|
+ (void *)(SDLDropTarget_DragLeave),
|
|
|
+ (void *)(SDLDropTarget_Drop)
|
|
|
+};
|
|
|
+
|
|
|
void WIN_AcceptDragAndDrop(SDL_Window *window, SDL_bool accept)
|
|
|
{
|
|
|
- const SDL_WindowData *data = window->internal;
|
|
|
- DragAcceptFiles(data->hwnd, accept ? TRUE : FALSE);
|
|
|
+ SDL_WindowData *data = window->internal;
|
|
|
+ if (data->videodata->oleinitialized) {
|
|
|
+ if (accept && !data->drop_target) {
|
|
|
+ SDLDropTarget *drop_target = (SDLDropTarget *)SDL_calloc(1, sizeof(SDLDropTarget));
|
|
|
+ if (drop_target != NULL) {
|
|
|
+ drop_target->lpVtbl = vtDropTarget;
|
|
|
+ drop_target->window = window;
|
|
|
+ drop_target->hwnd = data->hwnd;
|
|
|
+ drop_target->format_file = RegisterClipboardFormat(L"text/uri-list");
|
|
|
+ drop_target->format_text = RegisterClipboardFormat(L"text/plain;charset=utf-8");
|
|
|
+ data->drop_target = drop_target;
|
|
|
+ SDLDropTarget_AddRef(drop_target);
|
|
|
+ RegisterDragDrop(data->hwnd, (LPDROPTARGET)drop_target);
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Accept Drag and Drop, window %u, enabled Full OLE IDropTarget\n",
|
|
|
+ window->id);
|
|
|
+ }
|
|
|
+ } else if (!accept && data->drop_target) {
|
|
|
+ RevokeDragDrop(data->hwnd);
|
|
|
+ SDLDropTarget_Release(data->drop_target);
|
|
|
+ data->drop_target = NULL;
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Accept Drag and Drop, window %u, disabled Full OLE IDropTarget\n",
|
|
|
+ window->id);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ DragAcceptFiles(data->hwnd, accept ? TRUE : FALSE);
|
|
|
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
|
|
+ ". In Accept Drag and Drop, window %u, %s Fallback WM_DROPFILES\n",
|
|
|
+ window->id, (accept ? "enabled" : "disabled"));
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
int WIN_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation)
|