From 0af8ec08f8097b5cdbe86260565b00a068afc4ec Mon Sep 17 00:00:00 2001 From: James Ross-Gowan Date: Sat, 25 Mar 2017 23:30:54 +1100 Subject: w32_common: move the IDropTarget impl to a separate file This was mostly self-contained, so its removal makes w32_common.c a bit easier to read. Also, because it was self contained and its author has agreed to LGPL relicencing, the new file has the LGPL licence header. --- video/out/w32_common.c | 204 +------------------------------------ video/out/win32/droptarget.c | 233 +++++++++++++++++++++++++++++++++++++++++++ video/out/win32/droptarget.h | 33 ++++++ wscript_build.py | 1 + 4 files changed, 270 insertions(+), 201 deletions(-) create mode 100644 video/out/win32/droptarget.c create mode 100644 video/out/win32/droptarget.h diff --git a/video/out/w32_common.c b/video/out/w32_common.c index 287bb24618..18acaa4423 100644 --- a/video/out/w32_common.c +++ b/video/out/w32_common.c @@ -37,6 +37,7 @@ #include "win_state.h" #include "w32_common.h" #include "win32/displayconfig.h" +#include "win32/droptarget.h" #include "osdep/io.h" #include "osdep/threads.h" #include "osdep/w32_keyboard.h" @@ -148,203 +149,6 @@ struct vo_w32_state { HANDLE avrt_handle; }; -typedef struct tagDropTarget { - IDropTarget iface; - atomic_int refCnt; - DWORD lastEffect; - IDataObject* dataObj; - struct vo_w32_state *w32; -} DropTarget; - -static FORMATETC fmtetc_file = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; -static FORMATETC fmtetc_url = { 0, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; - -static void DropTarget_Destroy(DropTarget* This) -{ - if (This->dataObj != NULL) { - This->dataObj->lpVtbl->Release(This->dataObj); - This->dataObj->lpVtbl = NULL; - } - - talloc_free(This); -} - -static HRESULT STDMETHODCALLTYPE DropTarget_QueryInterface(IDropTarget* This, - REFIID riid, - void** ppvObject) -{ - if (!IsEqualGUID(riid, &IID_IUnknown) || - !IsEqualGUID(riid, &IID_IDataObject)) { - *ppvObject = NULL; - return E_NOINTERFACE; - } - - *ppvObject = This; - This->lpVtbl->AddRef(This); - return S_OK; -} - -static ULONG STDMETHODCALLTYPE DropTarget_AddRef(IDropTarget* This) -{ - DropTarget* t = (DropTarget*)This; - return atomic_fetch_add(&t->refCnt, 1) + 1; -} - -static ULONG STDMETHODCALLTYPE DropTarget_Release(IDropTarget* This) -{ - DropTarget* t = (DropTarget*)This; - ULONG cRef = atomic_fetch_add(&t->refCnt, -1) - 1; - - if (cRef == 0) { - DropTarget_Destroy(t); - } - - return cRef; -} - -static HRESULT STDMETHODCALLTYPE DropTarget_DragEnter(IDropTarget* This, - IDataObject* pDataObj, - DWORD grfKeyState, - POINTL pt, - DWORD* pdwEffect) -{ - DropTarget* t = (DropTarget*)This; - - pDataObj->lpVtbl->AddRef(pDataObj); - if (pDataObj->lpVtbl->QueryGetData(pDataObj, &fmtetc_file) != S_OK && - pDataObj->lpVtbl->QueryGetData(pDataObj, &fmtetc_url) != S_OK) { - - *pdwEffect = DROPEFFECT_NONE; - } - - if (t->dataObj != NULL) { - t->dataObj->lpVtbl->Release(t->dataObj); - } - - t->dataObj = pDataObj; - t->lastEffect = *pdwEffect; - return S_OK; -} - -static HRESULT STDMETHODCALLTYPE DropTarget_DragOver(IDropTarget* This, - DWORD grfKeyState, - POINTL pt, - DWORD* pdwEffect) -{ - DropTarget* t = (DropTarget*)This; - - *pdwEffect = t->lastEffect; - return S_OK; -} - -static HRESULT STDMETHODCALLTYPE DropTarget_DragLeave(IDropTarget* This) -{ - DropTarget* t = (DropTarget*)This; - - if (t->dataObj != NULL) { - t->dataObj->lpVtbl->Release(t->dataObj); - t->dataObj = NULL; - } - - return S_OK; -} - -static HRESULT STDMETHODCALLTYPE DropTarget_Drop(IDropTarget* This, - IDataObject* pDataObj, - DWORD grfKeyState, POINTL pt, - DWORD* pdwEffect) -{ - DropTarget* t = (DropTarget*)This; - - STGMEDIUM medium; - - if (t->dataObj != NULL) { - t->dataObj->lpVtbl->Release(t->dataObj); - t->dataObj = NULL; - } - - enum mp_dnd_action action = (grfKeyState & MK_SHIFT) ? DND_APPEND : DND_REPLACE; - - pDataObj->lpVtbl->AddRef(pDataObj); - - if (pDataObj->lpVtbl->GetData(pDataObj, &fmtetc_file, &medium) == S_OK) { - if (GlobalLock(medium.hGlobal) != NULL) { - HDROP hDrop = (HDROP)medium.hGlobal; - - UINT numFiles = DragQueryFileW(hDrop, 0xFFFFFFFF, NULL, 0); - char** files = talloc_zero_array(NULL, char*, numFiles); - - UINT nrecvd_files = 0; - for (UINT i = 0; i < numFiles; i++) { - UINT len = DragQueryFileW(hDrop, i, NULL, 0); - wchar_t* buf = talloc_array(NULL, wchar_t, len + 1); - - if (DragQueryFileW(hDrop, i, buf, len + 1) == len) { - char* fname = mp_to_utf8(files, buf); - files[nrecvd_files++] = fname; - - MP_VERBOSE(t->w32, "received dropped file: %s\n", - fname); - } else { - MP_ERR(t->w32, "error getting dropped file name\n"); - } - - talloc_free(buf); - } - - GlobalUnlock(medium.hGlobal); - mp_event_drop_files(t->w32->input_ctx, nrecvd_files, files, - action); - - talloc_free(files); - } - - ReleaseStgMedium(&medium); - } else if (pDataObj->lpVtbl->GetData(pDataObj, - &fmtetc_url, &medium) == S_OK) { - // get the URL encoded in US-ASCII - wchar_t* wurl = GlobalLock(medium.hGlobal); - if (wurl != NULL) { - char *url = mp_to_utf8(NULL, wurl); - if (mp_event_drop_mime_data(t->w32->input_ctx, "text/uri-list", - bstr0(url), action) > 0) { - MP_VERBOSE(t->w32, "received dropped URL: %s\n", url); - } else { - MP_ERR(t->w32, "error getting dropped URL\n"); - } - - talloc_free(url); - GlobalUnlock(medium.hGlobal); - } - - ReleaseStgMedium(&medium); - } - else { - t->lastEffect = DROPEFFECT_NONE; - } - - pDataObj->lpVtbl->Release(pDataObj); - *pdwEffect = t->lastEffect; - return S_OK; -} - - -static void DropTarget_Init(DropTarget* This, struct vo_w32_state *w32) -{ - IDropTargetVtbl* vtbl = talloc(This, IDropTargetVtbl); - *vtbl = (IDropTargetVtbl){ - DropTarget_QueryInterface, DropTarget_AddRef, DropTarget_Release, - DropTarget_DragEnter, DropTarget_DragOver, DropTarget_DragLeave, - DropTarget_Drop - }; - - This->iface.lpVtbl = vtbl; - atomic_store(&This->refCnt, 0); - This->lastEffect = 0; - This->dataObj = NULL; - This->w32 = w32; -} - static void add_window_borders(HWND hwnd, RECT *rc) { AdjustWindowRect(rc, GetWindowLongPtrW(hwnd, GWL_STYLE), 0); @@ -1536,10 +1340,8 @@ static void *gui_thread(void *ptr) if (SUCCEEDED(OleInitialize(NULL))) { ole_ok = true; - fmtetc_url.cfFormat = (CLIPFORMAT)RegisterClipboardFormat(TEXT("UniformResourceLocatorW")); - DropTarget* dropTarget = talloc(NULL, DropTarget); - DropTarget_Init(dropTarget, w32); - RegisterDragDrop(w32->window, &dropTarget->iface); + IDropTarget *dt = mp_w32_droptarget_create(w32->log, w32->input_ctx); + RegisterDragDrop(w32->window, dt); // ITaskbarList2 has the MarkFullscreenWindow method, which is used to // make sure the taskbar is hidden when mpv goes fullscreen diff --git a/video/out/win32/droptarget.c b/video/out/win32/droptarget.c new file mode 100644 index 0000000000..8da484439f --- /dev/null +++ b/video/out/win32/droptarget.c @@ -0,0 +1,233 @@ +/* + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see . + */ + +#include +#include +#include + +#include "common/msg.h" +#include "common/common.h" +#include "input/input.h" +#include "input/event.h" +#include "osdep/atomic.h" +#include "osdep/io.h" +#include "mpv_talloc.h" + +#include "droptarget.h" + +typedef struct tagDropTarget { + IDropTarget iface; + atomic_int refCnt; + DWORD lastEffect; + IDataObject* dataObj; + struct mp_log *log; + struct input_ctx *input_ctx; +} DropTarget; + +static FORMATETC fmtetc_file = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; +static FORMATETC fmtetc_url = { 0, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + +static void DropTarget_Destroy(DropTarget* This) +{ + if (This->dataObj != NULL) { + This->dataObj->lpVtbl->Release(This->dataObj); + This->dataObj->lpVtbl = NULL; + } + + talloc_free(This); +} + +static HRESULT STDMETHODCALLTYPE DropTarget_QueryInterface(IDropTarget* This, + REFIID riid, + void** ppvObject) +{ + if (!IsEqualGUID(riid, &IID_IUnknown) || + !IsEqualGUID(riid, &IID_IDataObject)) { + *ppvObject = NULL; + return E_NOINTERFACE; + } + + *ppvObject = This; + This->lpVtbl->AddRef(This); + return S_OK; +} + +static ULONG STDMETHODCALLTYPE DropTarget_AddRef(IDropTarget* This) +{ + DropTarget* t = (DropTarget*)This; + return atomic_fetch_add(&t->refCnt, 1) + 1; +} + +static ULONG STDMETHODCALLTYPE DropTarget_Release(IDropTarget* This) +{ + DropTarget* t = (DropTarget*)This; + ULONG cRef = atomic_fetch_add(&t->refCnt, -1) - 1; + + if (cRef == 0) { + DropTarget_Destroy(t); + } + + return cRef; +} + +static HRESULT STDMETHODCALLTYPE DropTarget_DragEnter(IDropTarget* This, + IDataObject* pDataObj, + DWORD grfKeyState, + POINTL pt, + DWORD* pdwEffect) +{ + DropTarget* t = (DropTarget*)This; + + pDataObj->lpVtbl->AddRef(pDataObj); + if (pDataObj->lpVtbl->QueryGetData(pDataObj, &fmtetc_file) != S_OK && + pDataObj->lpVtbl->QueryGetData(pDataObj, &fmtetc_url) != S_OK) { + + *pdwEffect = DROPEFFECT_NONE; + } + + if (t->dataObj != NULL) { + t->dataObj->lpVtbl->Release(t->dataObj); + } + + t->dataObj = pDataObj; + t->lastEffect = *pdwEffect; + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE DropTarget_DragOver(IDropTarget* This, + DWORD grfKeyState, + POINTL pt, + DWORD* pdwEffect) +{ + DropTarget* t = (DropTarget*)This; + + *pdwEffect = t->lastEffect; + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE DropTarget_DragLeave(IDropTarget* This) +{ + DropTarget* t = (DropTarget*)This; + + if (t->dataObj != NULL) { + t->dataObj->lpVtbl->Release(t->dataObj); + t->dataObj = NULL; + } + + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE DropTarget_Drop(IDropTarget* This, + IDataObject* pDataObj, + DWORD grfKeyState, POINTL pt, + DWORD* pdwEffect) +{ + DropTarget* t = (DropTarget*)This; + + STGMEDIUM medium; + + if (t->dataObj != NULL) { + t->dataObj->lpVtbl->Release(t->dataObj); + t->dataObj = NULL; + } + + enum mp_dnd_action action = (grfKeyState & MK_SHIFT) ? DND_APPEND : DND_REPLACE; + + pDataObj->lpVtbl->AddRef(pDataObj); + + if (pDataObj->lpVtbl->GetData(pDataObj, &fmtetc_file, &medium) == S_OK) { + if (GlobalLock(medium.hGlobal) != NULL) { + HDROP hDrop = (HDROP)medium.hGlobal; + + UINT numFiles = DragQueryFileW(hDrop, 0xFFFFFFFF, NULL, 0); + char** files = talloc_zero_array(NULL, char*, numFiles); + + UINT nrecvd_files = 0; + for (UINT i = 0; i < numFiles; i++) { + UINT len = DragQueryFileW(hDrop, i, NULL, 0); + wchar_t* buf = talloc_array(NULL, wchar_t, len + 1); + + if (DragQueryFileW(hDrop, i, buf, len + 1) == len) { + char* fname = mp_to_utf8(files, buf); + files[nrecvd_files++] = fname; + + MP_VERBOSE(t, "received dropped file: %s\n", fname); + } else { + MP_ERR(t, "error getting dropped file name\n"); + } + + talloc_free(buf); + } + + GlobalUnlock(medium.hGlobal); + mp_event_drop_files(t->input_ctx, nrecvd_files, files, + action); + + talloc_free(files); + } + + ReleaseStgMedium(&medium); + } else if (pDataObj->lpVtbl->GetData(pDataObj, + &fmtetc_url, &medium) == S_OK) { + // get the URL encoded in US-ASCII + wchar_t* wurl = GlobalLock(medium.hGlobal); + if (wurl != NULL) { + char *url = mp_to_utf8(NULL, wurl); + if (mp_event_drop_mime_data(t->input_ctx, "text/uri-list", + bstr0(url), action) > 0) { + MP_VERBOSE(t, "received dropped URL: %s\n", url); + } else { + MP_ERR(t, "error getting dropped URL\n"); + } + + talloc_free(url); + GlobalUnlock(medium.hGlobal); + } + + ReleaseStgMedium(&medium); + } + else { + t->lastEffect = DROPEFFECT_NONE; + } + + pDataObj->lpVtbl->Release(pDataObj); + *pdwEffect = t->lastEffect; + return S_OK; +} + +IDropTarget *mp_w32_droptarget_create(struct mp_log *log, + struct input_ctx *input_ctx) +{ + DropTarget* dropTarget = talloc(NULL, DropTarget); + IDropTargetVtbl* vtbl = talloc(dropTarget, IDropTargetVtbl); + *vtbl = (IDropTargetVtbl){ + DropTarget_QueryInterface, DropTarget_AddRef, DropTarget_Release, + DropTarget_DragEnter, DropTarget_DragOver, DropTarget_DragLeave, + DropTarget_Drop + }; + + fmtetc_url.cfFormat = (CLIPFORMAT)RegisterClipboardFormat(TEXT("UniformResourceLocatorW")); + + dropTarget->iface.lpVtbl = vtbl; + atomic_store(&dropTarget->refCnt, 0); + dropTarget->lastEffect = 0; + dropTarget->dataObj = NULL; + dropTarget->log = mp_log_new(dropTarget, log, "droptarget"); + dropTarget->input_ctx = input_ctx; + + return &dropTarget->iface; +} diff --git a/video/out/win32/droptarget.h b/video/out/win32/droptarget.h new file mode 100644 index 0000000000..53eb5ac998 --- /dev/null +++ b/video/out/win32/droptarget.h @@ -0,0 +1,33 @@ +/* + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see . + */ + +#ifndef MP_WIN32_DROPTARGET_H_ +#define MP_WIN32_DROPTARGET_H_ + +#include +#include +#include + +#include "input/input.h" +#include "common/msg.h" +#include "common/common.h" + +// Create a IDropTarget implementation that sends dropped files to input_ctx +IDropTarget *mp_w32_droptarget_create(struct mp_log *log, + struct input_ctx *input_ctx); + +#endif diff --git a/wscript_build.py b/wscript_build.py index 4f1d3440c0..7d112782a5 100644 --- a/wscript_build.py +++ b/wscript_build.py @@ -398,6 +398,7 @@ def build(ctx): ( "video/out/vo_xv.c", "xv" ), ( "video/out/w32_common.c", "win32" ), ( "video/out/win32/displayconfig.c", "win32" ), + ( "video/out/win32/droptarget.c", "win32" ), ( "video/out/win32/exclusive_hack.c", "gl-win32" ), ( "video/out/wayland_common.c", "wayland" ), ( "video/out/wayland/buffer.c", "wayland" ), -- cgit v1.2.3