summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--video/out/w32_common.c204
-rw-r--r--video/out/win32/droptarget.c233
-rw-r--r--video/out/win32/droptarget.h33
-rw-r--r--wscript_build.py1
4 files changed, 270 insertions, 201 deletions
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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <windows.h>
+#include <ole2.h>
+#include <shobjidl.h>
+
+#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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MP_WIN32_DROPTARGET_H_
+#define MP_WIN32_DROPTARGET_H_
+
+#include <windows.h>
+#include <ole2.h>
+#include <shobjidl.h>
+
+#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" ),