summaryrefslogtreecommitdiff
path: root/legacy
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2008-12-01 22:43:04 +0000
committerVincent Torri <vincent.torri@gmail.com>2008-12-01 22:43:04 +0000
commit1a897239c71ad8af78dbf80f058a4351e19aaae0 (patch)
tree9f86269464d6f742caf2a80571303454d975dd4d /legacy
parent6a06a92ac8d7f7a710a95271b40638270613be12 (diff)
Patch by Dmitriy Mazovka:
add drag'n drop support in ecore_win32 (reworked) (missing files) SVN revision: 37890
Diffstat (limited to 'legacy')
-rwxr-xr-xlegacy/ecore/src/lib/ecore_win32/ecore_win32_dnd.c133
-rw-r--r--legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_data_object.cpp209
-rw-r--r--legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_data_object.h49
-rw-r--r--legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_drop_source.cpp92
-rw-r--r--legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_drop_source.h36
-rw-r--r--legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_drop_target.cpp232
-rw-r--r--legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_drop_target.h47
-rw-r--r--legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_enumformatetc.cpp157
-rw-r--r--legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_enumformatetc.h50
9 files changed, 1005 insertions, 0 deletions
diff --git a/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd.c b/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd.c
new file mode 100755
index 0000000000..6ce9367ece
--- /dev/null
+++ b/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd.c
@@ -0,0 +1,133 @@
1/*
2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3 */
4
5#ifdef HAVE_CONFIG_H
6# include <config.h>
7#endif
8
9#include <windows.h>
10
11#include "Ecore_Win32.h"
12#include "ecore_win32_private.h"
13
14
15static int _ecore_win32_dnd_init_count = 0;
16
17static HANDLE DataToHandle(const char *data, int size)
18{
19 char *ptr;
20 ptr = (char *)GlobalAlloc(GMEM_FIXED, size);
21 memcpy(ptr, data, size);
22 return ptr;
23}
24
25
26int
27ecore_win32_dnd_init()
28{
29 if (_ecore_win32_dnd_init_count > 0)
30 {
31 _ecore_win32_dnd_init_count++;
32 return _ecore_win32_dnd_init_count;
33 }
34
35 if (OleInitialize(NULL) != S_OK)
36 return 0;
37
38 _ecore_win32_dnd_init_count++;
39
40 return _ecore_win32_dnd_init_count;
41}
42
43int ecore_win32_dnd_shutdown()
44{
45 _ecore_win32_dnd_init_count--;
46 if (_ecore_win32_dnd_init_count > 0) return _ecore_win32_dnd_init_count;
47
48 OleUninitialize();
49
50 if (_ecore_win32_dnd_init_count < 0) _ecore_win32_dnd_init_count = 0;
51
52 return _ecore_win32_dnd_init_count;
53}
54
55int ecore_win32_dnd_begin(const char *data,
56 int size)
57{
58 if (data == NULL)
59 return 0;
60 if (size < 0)
61 size = strlen(data) + 1;
62
63 IDataObject *pDataObject = NULL;
64 IDropSource *pDropSource = NULL;
65
66 FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
67 STGMEDIUM stgmed = { TYMED_HGLOBAL, { 0 }, 0 };
68
69 stgmed.hGlobal = DataToHandle(data, size);
70
71 int res = 0;
72
73 // create the data object
74 pDataObject = (IDataObject *)_ecore_win32_dnd_data_object_new((void *)&fmtetc,
75 (void *)&stgmed,
76 1);
77 pDropSource = (IDropSource *)_ecore_win32_dnd_drop_source_new();
78
79 if (pDataObject && pDropSource)
80 {
81 DWORD dwResult;
82 DWORD dwEffect = DROPEFFECT_COPY;
83
84 // do the drag-drop!
85 dwResult = DoDragDrop(pDataObject, pDropSource, DROPEFFECT_COPY, &dwEffect);
86
87 // finished. Check the return values to see if we need to do anything else
88 if (dwResult == DRAGDROP_S_DROP)
89 {
90 //printf(">>> \"%s\" Dropped <<<\n", str);
91 if(dwEffect == DROPEFFECT_MOVE)
92 {
93 // remove the data we just dropped from active document
94 }
95 }
96 //else if (dwResult == DRAGDROP_S_CANCEL)
97 // printf("DND cancelled\n");
98 //else
99 // printf("DND error\n");
100
101 res = 1;
102 }
103
104 _ecore_win32_dnd_data_object_free(pDataObject);
105 _ecore_win32_dnd_drop_source_free(pDropSource);
106
107 // cleanup
108 ReleaseStgMedium(&stgmed);
109 return (int)res;
110}
111
112int ecore_win32_dnd_register_drop_target(Ecore_Win32_Window *window,
113 Ecore_Win32_Dnd_DropTarget_Callback callback)
114{
115 if (window == NULL)
116 return 0;
117
118 struct _Ecore_Win32_Window *wnd = (struct _Ecore_Win32_Window *)window;
119 wnd->dnd_drop_target = _ecore_win32_dnd_register_drop_window(wnd->window,
120 callback,
121 (void *)wnd);
122 return (int)(wnd->dnd_drop_target != NULL);
123}
124
125void ecore_win32_dnd_unregister_drop_target(Ecore_Win32_Window *window)
126{
127 if (window == NULL)
128 return;
129
130 struct _Ecore_Win32_Window *wnd = (struct _Ecore_Win32_Window *)window;
131 if (wnd->dnd_drop_target != NULL)
132 _ecore_win32_dnd_unregister_drop_window(wnd->window, wnd->dnd_drop_target);
133}
diff --git a/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_data_object.cpp b/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_data_object.cpp
new file mode 100644
index 0000000000..6de10356ea
--- /dev/null
+++ b/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_data_object.cpp
@@ -0,0 +1,209 @@
1/*
2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3 */
4
5#ifdef HAVE_CONFIG_H
6# include <config.h>
7#endif
8
9#include <assert.h>
10
11#define WIN32_LEAN_AND_MEAN
12#include <windows.h>
13#undef WIN32_LEAN_AND_MEAN
14#include <ole2.h>
15
16#include "Ecore_Win32.h"
17#include "ecore_win32_private.h"
18
19#include "ecore_win32_dnd_enumformatetc.h"
20#include "ecore_win32_dnd_data_object.h"
21
22
23static HGLOBAL DupGlobalMem(HGLOBAL hMem)
24{
25 DWORD len = (DWORD)GlobalSize(hMem);
26 PVOID source = GlobalLock(hMem);
27 PVOID dest = GlobalAlloc(GMEM_FIXED, len);
28 memcpy(dest, source, len);
29 GlobalUnlock(hMem);
30 return dest;
31}
32
33// structors
34
35DataObject::DataObject(FORMATETC *fmtetc, STGMEDIUM *stgmed, int count)
36{
37 assert(fmtetc != NULL);
38 assert(stgmed != NULL);
39 assert(count > 0);
40
41 // reference count must ALWAYS start at 1
42 ref_count_ = 1;
43 formats_num_ = count;
44
45 format_etc_ = new FORMATETC[count];
46 stg_medium_ = new STGMEDIUM[count];
47
48 for(int i = 0; i < count; i++)
49 {
50 format_etc_[i] = fmtetc[i];
51 stg_medium_[i] = stgmed[i];
52 }
53}
54
55DataObject::~DataObject()
56{
57 delete[] format_etc_;
58 delete[] stg_medium_;
59}
60
61
62// IUnknown
63
64HRESULT DataObject::QueryInterface(REFIID iid, void **ppvObject)
65{
66 // check to see what interface has been requested
67 if ((iid == IID_IDataObject) || (iid == IID_IUnknown))
68 {
69 AddRef();
70 *ppvObject = this;
71 return S_OK;
72 }
73 *ppvObject = 0;
74 return E_NOINTERFACE;
75}
76
77ULONG DataObject::AddRef()
78{
79 return InterlockedIncrement(&ref_count_);
80}
81
82ULONG DataObject::Release()
83{
84 LONG count = InterlockedDecrement(&ref_count_);
85 if(count == 0)
86 {
87 delete this;
88 return 0;
89 }
90 return count;
91}
92
93// IDataObject
94
95HRESULT DataObject::GetData(FORMATETC *pFormatEtc, STGMEDIUM *pMedium)
96{
97 assert(pMedium != NULL);
98 int idx;
99
100 // try to match the specified FORMATETC with one of our supported formats
101 if((idx = lookup_format_etc(pFormatEtc)) == -1)
102 return DV_E_FORMATETC;
103
104 // found a match - transfer data into supplied storage medium
105 pMedium->tymed = format_etc_[idx].tymed;
106 pMedium->pUnkForRelease = 0;
107
108 // copy the data into the caller's storage medium
109 switch(format_etc_[idx].tymed)
110 {
111 case TYMED_HGLOBAL:
112 pMedium->hGlobal = DupGlobalMem(stg_medium_[idx].hGlobal);
113 break;
114
115 default:
116 return DV_E_FORMATETC;
117 }
118
119 return S_OK;
120}
121
122HRESULT DataObject::GetDataHere(FORMATETC *pFormatEtc, STGMEDIUM *pmedium)
123{
124 return DATA_E_FORMATETC;
125}
126
127HRESULT DataObject::QueryGetData(FORMATETC *pFormatEtc)
128{
129 return (lookup_format_etc(pFormatEtc) == -1) ? DV_E_FORMATETC : S_OK;
130}
131
132HRESULT DataObject::GetCanonicalFormatEtc(FORMATETC *pFormatEct, FORMATETC *pFormatEtcOut)
133{
134 // Apparently we have to set this field to NULL even though we don't do anything else
135 pFormatEtcOut->ptd = NULL;
136 return E_NOTIMPL;
137}
138
139HRESULT DataObject::SetData(FORMATETC *pFormatEtc, STGMEDIUM *pMedium, BOOL fRelease)
140{
141 return E_NOTIMPL;
142}
143
144HRESULT DataObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppEnumFormatEtc)
145{
146 // only the get direction is supported for OLE
147 if(dwDirection == DATADIR_GET)
148 {
149 // for Win2k+ you can use the SHCreateStdEnumFmtEtc API call, however
150 // to support all Windows platforms we need to implement IEnumFormatEtc ourselves.
151 return CreateEnumFormatEtc(formats_num_, format_etc_, ppEnumFormatEtc);
152 }
153 else
154 {
155 // the direction specified is not supported for drag+drop
156 return E_NOTIMPL;
157 }
158}
159
160HRESULT DataObject::DAdvise(FORMATETC *pFormatEtc, DWORD advf, IAdviseSink *, DWORD *)
161{
162 return OLE_E_ADVISENOTSUPPORTED;
163}
164
165HRESULT DataObject::DUnadvise(DWORD dwConnection)
166{
167 return OLE_E_ADVISENOTSUPPORTED;
168}
169
170HRESULT DataObject::EnumDAdvise(IEnumSTATDATA **ppEnumAdvise)
171{
172 return OLE_E_ADVISENOTSUPPORTED;
173}
174
175// internal helper function
176
177int DataObject::lookup_format_etc(FORMATETC *pFormatEtc)
178{
179 // check each of our formats in turn to see if one matches
180 for(int i = 0; i < formats_num_; i++)
181 {
182 if((format_etc_[i].tymed & pFormatEtc->tymed) &&
183 (format_etc_[i].cfFormat == pFormatEtc->cfFormat) &&
184 (format_etc_[i].dwAspect == pFormatEtc->dwAspect))
185 {
186 // return index of stored format
187 return i;
188 }
189 }
190
191 // error, format not found
192 return -1;
193}
194
195void *_ecore_win32_dnd_data_object_new(void *fmtetc, void *stgmeds, int count)
196{
197 IDataObject *object = new DataObject((FORMATETC *)fmtetc, (STGMEDIUM *)stgmeds, (UINT)count);
198 assert(object != NULL);
199 return object;
200}
201
202void _ecore_win32_dnd_data_object_free(void *data_object)
203{
204 if (!data_object)
205 return;
206
207 IDataObject *object = (IDataObject *)data_object;
208 object->Release();
209}
diff --git a/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_data_object.h b/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_data_object.h
new file mode 100644
index 0000000000..3d289cf7f5
--- /dev/null
+++ b/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_data_object.h
@@ -0,0 +1,49 @@
1#ifndef __ECORE_WIN32_DND_DATA_OBJECT_H__
2#define __ECORE_WIN32_DND_DATA_OBJECT_H__
3
4
5#define WIN32_LEAN_AND_MEAN
6#include <windows.h>
7#undef WIN32_LEAN_AND_MEAN
8#include <objbase.h>
9
10
11class DataObject : public IDataObject
12{
13 private:
14
15 LONG ref_count_;
16 int formats_num_;
17 FORMATETC *format_etc_;
18 STGMEDIUM *stg_medium_;
19
20 private: // internal helper function
21
22 int lookup_format_etc(FORMATETC *format_etc);
23
24 public: // structors
25
26 DataObject(FORMATETC *fmtetc, STGMEDIUM *stgmed, int count);
27 ~DataObject();
28
29 public: // IUnknown
30
31 HRESULT __stdcall QueryInterface(REFIID iid, void **ppvObject);
32 ULONG __stdcall AddRef();
33 ULONG __stdcall Release();
34
35 public: // IDataObject
36
37 HRESULT __stdcall GetData(FORMATETC *pFormatEtc, STGMEDIUM *pmedium);
38 HRESULT __stdcall GetDataHere(FORMATETC *pFormatEtc, STGMEDIUM *pmedium);
39 HRESULT __stdcall QueryGetData(FORMATETC *pFormatEtc);
40 HRESULT __stdcall GetCanonicalFormatEtc(FORMATETC *pFormatEct, FORMATETC *pFormatEtcOut);
41 HRESULT __stdcall SetData(FORMATETC *pFormatEtc, STGMEDIUM *pMedium, BOOL fRelease);
42 HRESULT __stdcall EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppEnumFormatEtc);
43 HRESULT __stdcall DAdvise(FORMATETC *pFormatEtc, DWORD advf, IAdviseSink *, DWORD *);
44 HRESULT __stdcall DUnadvise(DWORD dwConnection);
45 HRESULT __stdcall EnumDAdvise(IEnumSTATDATA **ppEnumAdvise);
46};
47
48
49#endif /* __ECORE_WIN32_DND_DATA_OBJECT_H__ */
diff --git a/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_drop_source.cpp b/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_drop_source.cpp
new file mode 100644
index 0000000000..065ac6ac23
--- /dev/null
+++ b/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_drop_source.cpp
@@ -0,0 +1,92 @@
1/*
2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3 */
4
5#ifdef HAVE_CONFIG_H
6# include <config.h>
7#endif
8
9#include <assert.h>
10
11#include "ecore_win32_dnd_drop_source.h"
12
13#include "ecore_win32_private.h"
14
15// structors
16
17// reference count must ALWAYS start at 1
18DropSource::DropSource() : ref_count_(1)
19{ }
20
21
22// IUnknown
23
24HRESULT DropSource::QueryInterface(REFIID iid, void **ppvObject)
25{
26 // check to see what interface has been requested
27 if (iid == IID_IDropSource || iid == IID_IUnknown)
28 {
29 AddRef();
30 *ppvObject = this;
31 return S_OK;
32 }
33 *ppvObject = 0;
34 return E_NOINTERFACE;
35}
36
37ULONG DropSource::AddRef()
38{
39 return InterlockedIncrement(&ref_count_);
40}
41
42ULONG DropSource::Release()
43{
44 LONG count = InterlockedDecrement(&ref_count_);
45 if(count == 0)
46 {
47 delete this;
48 return 0;
49 }
50 return count;
51}
52
53
54// IDropSource
55
56HRESULT DropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
57{
58 // if the Escape key has been pressed since the last call, cancel the drop
59 if(fEscapePressed == TRUE)
60 return DRAGDROP_S_CANCEL;
61
62 // if the LeftMouse button has been released, then do the drop!
63 if((grfKeyState & MK_LBUTTON) == 0)
64 return DRAGDROP_S_DROP;
65
66 // continue with the drag-drop
67 return S_OK;
68}
69
70HRESULT DropSource::GiveFeedback(DWORD dwEffect)
71{
72 return DRAGDROP_S_USEDEFAULTCURSORS;
73}
74
75
76// ecore_win32 private functions
77
78void *_ecore_win32_dnd_drop_source_new()
79{
80 IDropSource *object = new DropSource();
81 assert(object != NULL);
82 return object;
83}
84
85void _ecore_win32_dnd_drop_source_free(void *drop_source)
86{
87 if (!drop_source)
88 return;
89
90 IDropSource *object = (IDropSource *)drop_source;
91 object->Release();
92}
diff --git a/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_drop_source.h b/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_drop_source.h
new file mode 100644
index 0000000000..9081f46a15
--- /dev/null
+++ b/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_drop_source.h
@@ -0,0 +1,36 @@
1#ifndef __ECORE_WIN32_DND_DROP_SOURCE_H__
2#define __ECORE_WIN32_DND_DROP_SOURCE_H__
3
4
5#define WIN32_LEAN_AND_MEAN
6#include <windows.h>
7#undef WIN32_LEAN_AND_MEAN
8#include <ole2.h>
9
10#include "Ecore_Win32.h"
11
12
13class DropSource : public IDropSource
14{
15 private:
16
17 LONG ref_count_;
18
19 public: // structors
20
21 DropSource();
22
23 public: // IUnknown
24
25 HRESULT __stdcall QueryInterface(REFIID iid, void ** ppvObject);
26 ULONG __stdcall AddRef();
27 ULONG __stdcall Release();
28
29 public: // IDropSource
30
31 HRESULT __stdcall QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState);
32 HRESULT __stdcall GiveFeedback(DWORD dwEffect);
33};
34
35
36#endif /* __ECORE_WIN32_DND_DROP_SOURCE_H__ */
diff --git a/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_drop_target.cpp b/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_drop_target.cpp
new file mode 100644
index 0000000000..50513164c8
--- /dev/null
+++ b/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_drop_target.cpp
@@ -0,0 +1,232 @@
1/*
2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3 */
4
5#ifdef HAVE_CONFIG_H
6# include <config.h>
7#endif
8
9#include "ecore_win32_dnd_drop_target.h"
10
11#include "ecore_win32_private.h"
12
13
14// structors
15
16DropTarget::DropTarget(HWND window, Ecore_Win32_Dnd_DropTarget_Callback callback, void *window_obj_ptr)
17 : ref_count_(1)
18 , window_(window)
19 , allow_drop_(false)
20 , drop_callback_(callback)
21 ,drop_callback_ptr_(window_obj_ptr)
22{ }
23
24
25// IUnknown
26
27HRESULT DropTarget::QueryInterface(REFIID iid, void **ppvObject)
28{
29 // check to see what interface has been requested
30 if (iid == IID_IDropTarget || iid == IID_IUnknown)
31 {
32 AddRef();
33 *ppvObject = this;
34 return S_OK;
35 }
36 *ppvObject = 0;
37
38 return E_NOINTERFACE;
39}
40
41ULONG DropTarget::AddRef()
42{
43 return InterlockedIncrement(&ref_count_);
44}
45
46ULONG DropTarget::Release()
47{
48 LONG count = InterlockedDecrement(&ref_count_);
49 if (count == 0)
50 {
51 delete this;
52 return 0;
53 }
54
55 return count;
56}
57
58
59// IDropTarget
60
61HRESULT DropTarget::DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
62{
63 // does the dataobject contain data we want?
64 allow_drop_ = QueryDataObject(pDataObject) &&
65 (drop_callback_ == NULL ||
66 (drop_callback_(drop_callback_ptr_, ECORE_WIN32_DND_EVENT_DRAG_ENTER, pt.x, pt.y, NULL, 0) != 0));
67
68 if (allow_drop_)
69 {
70 // get the dropeffect based on keyboard state
71 *pdwEffect = DropEffect(grfKeyState, pt, *pdwEffect);
72 SetFocus(window_);
73 //PositionCursor(_hwnd, pt);
74 }
75 else
76 *pdwEffect = DROPEFFECT_NONE;
77 return S_OK;
78}
79
80HRESULT DropTarget::DragOver(DWORD grfKeyState, POINTL pt, DWORD * pdwEffect)
81{
82 allow_drop_ =
83 (drop_callback_ == NULL) ||
84 (drop_callback_(drop_callback_ptr_, ECORE_WIN32_DND_EVENT_DRAG_OVER, pt.x, pt.y, NULL, 0) != 0);
85
86 if (allow_drop_)
87 {
88 *pdwEffect = DropEffect(grfKeyState, pt, *pdwEffect);
89 //PositionCursor(m_hWnd, pt);
90 }
91 else
92 {
93 *pdwEffect = DROPEFFECT_NONE;
94 }
95
96 return S_OK;
97}
98
99HRESULT DropTarget::DragLeave()
100{
101 POINT pt;
102
103 GetCursorPos(&pt);
104 if (drop_callback_ != NULL)
105 drop_callback_(drop_callback_ptr_, ECORE_WIN32_DND_EVENT_DRAG_LEAVE, pt.x, pt.y, NULL, 0);
106
107 return S_OK;
108}
109
110HRESULT DropTarget::Drop(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
111{
112 if (allow_drop_)
113 {
114 // construct a FORMATETC object
115 FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
116 STGMEDIUM stgmed;
117
118 // See if the dataobject contains any TEXT stored as a HGLOBAL
119 if (pDataObject->QueryGetData(&fmtetc) == S_OK)
120 {
121 // Yippie! the data is there, so go get it!
122 if (pDataObject->GetData(&fmtetc, &stgmed) == S_OK)
123 {
124 // we asked for the data as a HGLOBAL, so access it appropriately
125 PVOID data = GlobalLock(stgmed.hGlobal);
126 UINT size = GlobalSize(stgmed.hGlobal);
127
128 if (drop_callback_ != NULL)
129 {
130 drop_callback_(drop_callback_ptr_,
131 ECORE_WIN32_DND_EVENT_DROP,
132 pt.x, pt.y,
133 data, size);
134 }
135
136 GlobalUnlock(stgmed.hGlobal);
137
138 // release the data using the COM API
139 ReleaseStgMedium(&stgmed);
140 }
141 }
142 *pdwEffect = DropEffect(grfKeyState, pt, *pdwEffect);
143 }
144 else
145 {
146 *pdwEffect = DROPEFFECT_NONE;
147 }
148
149 return S_OK;
150}
151
152
153// internal helper function
154
155DWORD DropTarget::DropEffect(DWORD grfKeyState, POINTL pt, DWORD dwAllowed)
156{
157 DWORD dwEffect = 0;
158
159 // 1. check "pt" -> do we allow a drop at the specified coordinates?
160
161 // 2. work out that the drop-effect should be based on grfKeyState
162 if (grfKeyState & MK_CONTROL)
163 {
164 dwEffect = dwAllowed & DROPEFFECT_COPY;
165 }
166 else if (grfKeyState & MK_SHIFT)
167 {
168 dwEffect = dwAllowed & DROPEFFECT_MOVE;
169 }
170
171 // 3. no key-modifiers were specified (or drop effect not allowed), so
172 // base the effect on those allowed by the dropsource
173 if (dwEffect == 0)
174 {
175 if (dwAllowed & DROPEFFECT_COPY) dwEffect = DROPEFFECT_COPY;
176 if (dwAllowed & DROPEFFECT_MOVE) dwEffect = DROPEFFECT_MOVE;
177 }
178
179 return dwEffect;
180}
181
182bool DropTarget::QueryDataObject(IDataObject *pDataObject)
183{
184 FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
185
186 // does the data object support CF_TEXT using a HGLOBAL?
187 return pDataObject->QueryGetData(&fmtetc) == S_OK;
188}
189
190
191// ecore_win32 private functions
192
193void *_ecore_win32_dnd_register_drop_window(HWND hwnd, Ecore_Win32_Dnd_DropTarget_Callback callback, void *ptr)
194{
195 DropTarget *pDropTarget = new DropTarget(hwnd, callback, ptr);
196
197 if (pDropTarget == NULL)
198 return NULL;
199
200 // acquire a strong lock
201 if (FAILED(CoLockObjectExternal(pDropTarget, TRUE, FALSE)))
202 {
203 delete pDropTarget;
204 return NULL;
205 }
206
207 // tell OLE that the window is a drop target
208 if (FAILED(RegisterDragDrop(hwnd, pDropTarget)))
209 {
210 delete pDropTarget;
211 return NULL;
212 }
213
214 return pDropTarget;
215}
216
217void _ecore_win32_dnd_unregister_drop_window(HWND hwnd, void *drop_target)
218{
219 IDropTarget *pDropTarget = (IDropTarget *)drop_target;
220
221 if (drop_target == NULL)
222 return;
223
224 // remove drag+drop
225 RevokeDragDrop(hwnd);
226
227 // remove the strong lock
228 CoLockObjectExternal(pDropTarget, FALSE, TRUE);
229
230 // release our own reference
231 pDropTarget->Release();
232}
diff --git a/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_drop_target.h b/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_drop_target.h
new file mode 100644
index 0000000000..24c3de3e1a
--- /dev/null
+++ b/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_drop_target.h
@@ -0,0 +1,47 @@
1#ifndef __ECORE_WIN32_DND_DROP_TARGET_H__
2#define __ECORE_WIN32_DND_DROP_TARGET_H__
3
4
5#define WIN32_LEAN_AND_MEAN
6#include <windows.h>
7#undef WIN32_LEAN_AND_MEAN
8#include <ole2.h>
9
10#include "Ecore_Win32.h"
11
12
13class DropTarget : public IDropTarget
14{
15 private:
16
17 LONG ref_count_;
18 HWND window_;
19 bool allow_drop_;
20 Ecore_Win32_Dnd_DropTarget_Callback drop_callback_;
21 void *drop_callback_ptr_;
22
23 private: // internal helper function
24
25 DWORD DropEffect(DWORD grfKeyState, POINTL pt, DWORD dwAllowed);
26 bool QueryDataObject(IDataObject *pDataObject);
27
28 public: // structors
29
30 DropTarget(HWND hwnd, Ecore_Win32_Dnd_DropTarget_Callback callback, void *window_obj_ptr);
31
32public: // IUnknown
33
34 HRESULT __stdcall QueryInterface(REFIID iid, void ** ppvObject);
35 ULONG __stdcall AddRef();
36 ULONG __stdcall Release();
37
38 public: // IDropTarget
39
40 HRESULT __stdcall DragEnter(IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
41 HRESULT __stdcall DragOver(DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
42 HRESULT __stdcall DragLeave();
43 HRESULT __stdcall Drop(IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
44};
45
46
47#endif /* __ECORE_WIN32_DND_DROP_TARGET_H__ */
diff --git a/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_enumformatetc.cpp b/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_enumformatetc.cpp
new file mode 100644
index 0000000000..a3858bcdd8
--- /dev/null
+++ b/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_enumformatetc.cpp
@@ -0,0 +1,157 @@
1
2#include <ole2.h>
3
4#include "ecore_win32_dnd_enumformatetc.h"
5
6
7// structors
8
9CEnumFormatEtc::CEnumFormatEtc(FORMATETC *format_etc, int formats_num)
10 : ref_count_(1)
11 , index_(0)
12 , formats_num_(formats_num)
13 , format_etc_(new FORMATETC[formats_num])
14{
15 // make a new copy of each FORMATETC structure
16 for (unsigned int i = 0; i < formats_num_; i++)
17 {
18 DeepCopyFormatEtc(&format_etc_[i], &format_etc[i]);
19 }
20}
21
22CEnumFormatEtc::~CEnumFormatEtc()
23{
24 if (format_etc_)
25 {
26 // first free any DVTARGETDEVICE structures
27 for (ULONG i = 0; i < formats_num_; i++)
28 {
29 if (format_etc_[i].ptd)
30 CoTaskMemFree(format_etc_[i].ptd);
31 }
32
33 // now free the main array
34 delete[] format_etc_;
35 }
36}
37
38// IUnknown
39
40ULONG __stdcall CEnumFormatEtc::AddRef(void)
41{
42 // increment object reference count
43 return InterlockedIncrement(&ref_count_);
44}
45
46ULONG __stdcall CEnumFormatEtc::Release(void)
47{
48 // decrement object reference count
49 LONG count = InterlockedDecrement(&ref_count_);
50
51 if (count == 0)
52 {
53 delete this;
54 return 0;
55 }
56 else
57 {
58 return count;
59 }
60}
61
62HRESULT __stdcall CEnumFormatEtc::QueryInterface(REFIID iid, void **ppvObject)
63{
64 // check to see what interface has been requested
65 if ((iid == IID_IEnumFORMATETC) || (iid == IID_IUnknown))
66 {
67 AddRef();
68 *ppvObject = this;
69 return S_OK;
70 }
71 else
72 {
73 *ppvObject = 0;
74 return E_NOINTERFACE;
75 }
76}
77
78// IEnumFormatEtc
79
80HRESULT CEnumFormatEtc::Reset(void)
81{
82 index_ = 0;
83 return S_OK;
84}
85
86HRESULT CEnumFormatEtc::Skip(ULONG celt)
87{
88 index_ += celt;
89 return (index_ <= formats_num_) ? S_OK : S_FALSE;
90}
91
92HRESULT CEnumFormatEtc::Clone(IEnumFORMATETC **ppEnumFormatEtc)
93{
94 HRESULT hResult;
95
96 // make a duplicate enumerator
97 hResult = CreateEnumFormatEtc(formats_num_, format_etc_, ppEnumFormatEtc);
98
99 if (hResult == S_OK)
100 {
101 // manually set the index state
102 ((CEnumFormatEtc *)*ppEnumFormatEtc)->index_ = index_;
103 }
104
105 return hResult;
106}
107
108HRESULT CEnumFormatEtc::Next(ULONG celt, FORMATETC *pFormatEtc, ULONG *pceltFetched)
109{
110 ULONG copied = 0;
111
112 // validate arguments
113 if ((celt == 0) || (pFormatEtc == 0))
114 return E_INVALIDARG;
115
116 // copy the FORMATETC structures into the caller's buffer
117 while (index_ < formats_num_ && copied < celt)
118 {
119 DeepCopyFormatEtc(&pFormatEtc[copied], &format_etc_[index_]);
120 copied++;
121 index_++;
122 }
123
124 // store result
125 if (pceltFetched != 0)
126 *pceltFetched = copied;
127
128 // did we copy all that was requested?
129 return (copied == celt) ? S_OK : S_FALSE;
130}
131
132// external functions
133
134void DeepCopyFormatEtc(FORMATETC *dest, FORMATETC *source)
135{
136 // copy the source FORMATETC into dest
137 *dest = *source;
138
139 if (source->ptd)
140 {
141 // allocate memory for the DVTARGETDEVICE if necessary
142 dest->ptd = (DVTARGETDEVICE*)CoTaskMemAlloc(sizeof(DVTARGETDEVICE));
143
144 // copy the contents of the source DVTARGETDEVICE into dest->ptd
145 *(dest->ptd) = *(source->ptd);
146 }
147}
148
149HRESULT CreateEnumFormatEtc(UINT cfmt, FORMATETC *afmt, IEnumFORMATETC **ppEnumFormatEtc)
150{
151 if((cfmt == 0) || (afmt == 0) || (ppEnumFormatEtc == 0))
152 return E_INVALIDARG;
153
154 *ppEnumFormatEtc = new CEnumFormatEtc(afmt, cfmt);
155
156 return (*ppEnumFormatEtc) ? S_OK : E_OUTOFMEMORY;
157}
diff --git a/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_enumformatetc.h b/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_enumformatetc.h
new file mode 100644
index 0000000000..9f17f5684e
--- /dev/null
+++ b/legacy/ecore/src/lib/ecore_win32/ecore_win32_dnd_enumformatetc.h
@@ -0,0 +1,50 @@
1#ifndef __ECORE_WIN32_DND_ENUMFORMATETC_H__
2#define __ECORE_WIN32_DND_ENUMFORMATETC_H__
3
4
5#define WIN32_LEAN_AND_MEAN
6#include <windows.h>
7#undef WIN32_LEAN_AND_MEAN
8#include <objbase.h>
9
10
11class CEnumFormatEtc : public IEnumFORMATETC
12{
13 private:
14
15 LONG ref_count_; // Reference count for this COM interface
16 ULONG index_; // current enumerator index
17 ULONG formats_num_; // number of FORMATETC members
18 FORMATETC *format_etc_; // array of FORMATETC objects
19
20 public: // structors
21
22 CEnumFormatEtc(FORMATETC *pFormatEtc, int nNumFormats);
23
24 ~CEnumFormatEtc();
25
26 public: // IUnknown
27
28 HRESULT __stdcall QueryInterface (REFIID iid, void ** ppvObject);
29
30 ULONG __stdcall AddRef (void);
31
32 ULONG __stdcall Release (void);
33
34 public: // IEnumFormatEtc
35
36 HRESULT __stdcall Next (ULONG celt, FORMATETC * rgelt, ULONG * pceltFetched);
37
38 HRESULT __stdcall Skip (ULONG celt);
39
40 HRESULT __stdcall Reset (void);
41
42 HRESULT __stdcall Clone (IEnumFORMATETC ** ppEnumFormatEtc);
43};
44
45void DeepCopyFormatEtc(FORMATETC *dest, FORMATETC *source);
46
47HRESULT CreateEnumFormatEtc(UINT cfmt, FORMATETC *afmt, IEnumFORMATETC **ppEnumFormatEtc);
48
49
50#endif /* __ECORE_WIN32_DND_ENUMFORMATETC_H__ */