diff options
Diffstat (limited to 'libraries/ecore/src/lib/ecore_win32/ecore_win32_dnd_drop_target.cpp')
-rw-r--r-- | libraries/ecore/src/lib/ecore_win32/ecore_win32_dnd_drop_target.cpp | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/libraries/ecore/src/lib/ecore_win32/ecore_win32_dnd_drop_target.cpp b/libraries/ecore/src/lib/ecore_win32/ecore_win32_dnd_drop_target.cpp new file mode 100644 index 0000000..e19fb5d --- /dev/null +++ b/libraries/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 | |||
16 | DropTarget::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 | |||
27 | HRESULT 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 | |||
41 | ULONG DropTarget::AddRef() | ||
42 | { | ||
43 | return InterlockedIncrement(&ref_count_); | ||
44 | } | ||
45 | |||
46 | ULONG 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 | |||
61 | HRESULT 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 | |||
80 | HRESULT 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 | |||
99 | HRESULT 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 | |||
110 | HRESULT 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 | |||
155 | DWORD DropTarget::DropEffect(DWORD grfKeyState, POINTL pt __UNUSED__, 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 | |||
182 | bool 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 | |||
193 | void *_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 | |||
217 | void _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 | } | ||