diff options
author | Vincent Torri <vincent.torri@gmail.com> | 2008-12-01 22:43:04 +0000 |
---|---|---|
committer | Vincent Torri <vincent.torri@gmail.com> | 2008-12-01 22:43:04 +0000 |
commit | 1a897239c71ad8af78dbf80f058a4351e19aaae0 (patch) | |
tree | 9f86269464d6f742caf2a80571303454d975dd4d /legacy/ecore/src/lib | |
parent | 6a06a92ac8d7f7a710a95271b40638270613be12 (diff) |
Patch by Dmitriy Mazovka:
add drag'n drop support in ecore_win32 (reworked) (missing files)
SVN revision: 37890
Diffstat (limited to 'legacy/ecore/src/lib')
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 | |||
15 | static int _ecore_win32_dnd_init_count = 0; | ||
16 | |||
17 | static 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 | |||
26 | int | ||
27 | ecore_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 | |||
43 | int 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 | |||
55 | int 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 | |||
112 | int 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 | |||
125 | void 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 | |||
23 | static 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 | |||
35 | DataObject::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 | |||
55 | DataObject::~DataObject() | ||
56 | { | ||
57 | delete[] format_etc_; | ||
58 | delete[] stg_medium_; | ||
59 | } | ||
60 | |||
61 | |||
62 | // IUnknown | ||
63 | |||
64 | HRESULT 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 | |||
77 | ULONG DataObject::AddRef() | ||
78 | { | ||
79 | return InterlockedIncrement(&ref_count_); | ||
80 | } | ||
81 | |||
82 | ULONG 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 | |||
95 | HRESULT 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 | |||
122 | HRESULT DataObject::GetDataHere(FORMATETC *pFormatEtc, STGMEDIUM *pmedium) | ||
123 | { | ||
124 | return DATA_E_FORMATETC; | ||
125 | } | ||
126 | |||
127 | HRESULT DataObject::QueryGetData(FORMATETC *pFormatEtc) | ||
128 | { | ||
129 | return (lookup_format_etc(pFormatEtc) == -1) ? DV_E_FORMATETC : S_OK; | ||
130 | } | ||
131 | |||
132 | HRESULT 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 | |||
139 | HRESULT DataObject::SetData(FORMATETC *pFormatEtc, STGMEDIUM *pMedium, BOOL fRelease) | ||
140 | { | ||
141 | return E_NOTIMPL; | ||
142 | } | ||
143 | |||
144 | HRESULT 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 | |||
160 | HRESULT DataObject::DAdvise(FORMATETC *pFormatEtc, DWORD advf, IAdviseSink *, DWORD *) | ||
161 | { | ||
162 | return OLE_E_ADVISENOTSUPPORTED; | ||
163 | } | ||
164 | |||
165 | HRESULT DataObject::DUnadvise(DWORD dwConnection) | ||
166 | { | ||
167 | return OLE_E_ADVISENOTSUPPORTED; | ||
168 | } | ||
169 | |||
170 | HRESULT DataObject::EnumDAdvise(IEnumSTATDATA **ppEnumAdvise) | ||
171 | { | ||
172 | return OLE_E_ADVISENOTSUPPORTED; | ||
173 | } | ||
174 | |||
175 | // internal helper function | ||
176 | |||
177 | int 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 | |||
195 | void *_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 | |||
202 | void _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 | |||
11 | class 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 | ||
18 | DropSource::DropSource() : ref_count_(1) | ||
19 | { } | ||
20 | |||
21 | |||
22 | // IUnknown | ||
23 | |||
24 | HRESULT 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 | |||
37 | ULONG DropSource::AddRef() | ||
38 | { | ||
39 | return InterlockedIncrement(&ref_count_); | ||
40 | } | ||
41 | |||
42 | ULONG 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 | |||
56 | HRESULT 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 | |||
70 | HRESULT DropSource::GiveFeedback(DWORD dwEffect) | ||
71 | { | ||
72 | return DRAGDROP_S_USEDEFAULTCURSORS; | ||
73 | } | ||
74 | |||
75 | |||
76 | // ecore_win32 private functions | ||
77 | |||
78 | void *_ecore_win32_dnd_drop_source_new() | ||
79 | { | ||
80 | IDropSource *object = new DropSource(); | ||
81 | assert(object != NULL); | ||
82 | return object; | ||
83 | } | ||
84 | |||
85 | void _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 | |||
13 | class 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 | |||
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, 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 | } | ||
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 | |||
13 | class 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 | |||
32 | public: // 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 | |||
9 | CEnumFormatEtc::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 | |||
22 | CEnumFormatEtc::~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 | |||
40 | ULONG __stdcall CEnumFormatEtc::AddRef(void) | ||
41 | { | ||
42 | // increment object reference count | ||
43 | return InterlockedIncrement(&ref_count_); | ||
44 | } | ||
45 | |||
46 | ULONG __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 | |||
62 | HRESULT __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 | |||
80 | HRESULT CEnumFormatEtc::Reset(void) | ||
81 | { | ||
82 | index_ = 0; | ||
83 | return S_OK; | ||
84 | } | ||
85 | |||
86 | HRESULT CEnumFormatEtc::Skip(ULONG celt) | ||
87 | { | ||
88 | index_ += celt; | ||
89 | return (index_ <= formats_num_) ? S_OK : S_FALSE; | ||
90 | } | ||
91 | |||
92 | HRESULT 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 | |||
108 | HRESULT 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 | |||
134 | void 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 | |||
149 | HRESULT 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 | |||
11 | class 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 | |||
45 | void DeepCopyFormatEtc(FORMATETC *dest, FORMATETC *source); | ||
46 | |||
47 | HRESULT CreateEnumFormatEtc(UINT cfmt, FORMATETC *afmt, IEnumFORMATETC **ppEnumFormatEtc); | ||
48 | |||
49 | |||
50 | #endif /* __ECORE_WIN32_DND_ENUMFORMATETC_H__ */ | ||