4
4
// This file is released under the terms of the MIT license.
5
5
// Read LICENSE.txt for more information.
6
6
7
+ #include " base/fs.h"
7
8
#include " os/window.h"
8
9
#include " os/win/dnd.h"
9
10
#include " os/system.h"
@@ -68,6 +69,8 @@ class GLock {
68
69
69
70
operator T () { return m_data; }
70
71
72
+ T operator ->() { return m_data; }
73
+
71
74
bool operator ==(std::nullptr_t ) const { return m_data == nullptr ; }
72
75
bool operator !=(std::nullptr_t ) const { return m_data != nullptr ; }
73
76
@@ -108,13 +111,14 @@ class DataWrapper {
108
111
DataWrapper (IDataObject* data) : m_data(data) {}
109
112
110
113
template <typename T>
111
- Medium<T> get (CLIPFORMAT cfmt) {
114
+ Medium<T> get (CLIPFORMAT cfmt, LONG lindex = -1 )
115
+ {
112
116
STGMEDIUM medium;
113
117
FORMATETC fmt;
114
118
fmt.cfFormat = cfmt;
115
119
fmt.ptd = nullptr ;
116
120
fmt.dwAspect = DVASPECT_CONTENT;
117
- fmt.lindex = - 1 ;
121
+ fmt.lindex = lindex ;
118
122
fmt.tymed = TYMED::TYMED_HGLOBAL;
119
123
if (m_data->GetData (&fmt, &medium) != S_OK)
120
124
return nullptr ;
@@ -151,20 +155,20 @@ base::paths DragDataProviderWin::getPaths()
151
155
return files;
152
156
}
153
157
158
+ #if CLIP_ENABLE_IMAGE
154
159
SurfaceRef DragDataProviderWin::getImage ()
155
160
{
156
161
SurfaceRef surface = nullptr ;
157
- clip::image img;
158
162
159
163
DataWrapper data (m_data);
160
164
UINT png_format = RegisterClipboardFormatA (" PNG" );
161
165
if (png_format) {
162
166
Medium<uint8_t *> png_handle = data.get <uint8_t *>(png_format);
163
- if (png_handle != nullptr &&
164
- clip::win::read_png (png_handle, png_handle.size (), &img, nullptr ))
165
- return os::instance ()->makeSurface (img);
167
+ if (png_handle != nullptr )
168
+ return os::decode_png (png_handle, png_handle.size ());
166
169
}
167
170
171
+ clip::image img;
168
172
Medium<BITMAPV5HEADER*> b5 = data.get <BITMAPV5HEADER*>(CF_DIBV5);
169
173
if (b5 != nullptr ) {
170
174
clip::win::BitmapInfo bi (b5);
@@ -179,9 +183,40 @@ SurfaceRef DragDataProviderWin::getImage()
179
183
return os::instance ()->makeSurface (img);
180
184
}
181
185
186
+ // If there is a file descriptor available, then we inspect the first
187
+ // file of the group to see if its filename has any of the supported
188
+ // filename extensions for image formats.
189
+ UINT fileDescriptorFormat = RegisterClipboardFormat (CFSTR_FILEDESCRIPTOR);
190
+ UINT fileContentsFormat = RegisterClipboardFormat (CFSTR_FILECONTENTS);
191
+ if (fileDescriptorFormat) {
192
+ Medium<FILEGROUPDESCRIPTOR*> fgd = data.get <FILEGROUPDESCRIPTOR*>(fileDescriptorFormat);
193
+ if (fgd != nullptr && fgd->cItems > 0 ) {
194
+ // Get content of the first file on the group.
195
+ Medium<uint8_t *> content = data.get <uint8_t *>(fileContentsFormat, 0 );
196
+ if (content != nullptr ) {
197
+ std::string filename (base::to_utf8 (fgd->fgd ->cFileName ));
198
+ std::string ext = base::get_file_extension (filename);
199
+ std::transform (ext.begin (), ext.end (), ext.begin (), ::toupper);
200
+
201
+ if (ext == " PNG" )
202
+ return os::decode_png (content, content.size ());
203
+
204
+ if (ext == " JPG" || ext == " JPEG" || ext == " JPE" )
205
+ return os::decode_jpg (content, content.size ());
206
+
207
+ if (ext == " GIF" )
208
+ return os::decode_gif (content, content.size ());
209
+
210
+ if (ext == " BMP" )
211
+ return os::decode_bmp (content, content.size ());
212
+ }
213
+ }
214
+ }
215
+
182
216
// No suitable image format found.
183
217
return nullptr ;
184
218
}
219
+ #endif
185
220
186
221
std::string DragDataProviderWin::getUrl ()
187
222
{
@@ -203,6 +238,7 @@ bool DragDataProviderWin::contains(DragDataItemType type)
203
238
204
239
UINT urlFormat = RegisterClipboardFormat (CFSTR_INETURL);
205
240
UINT pngFormat = RegisterClipboardFormat (L" PNG" );
241
+ UINT fileDescriptorFormat = RegisterClipboardFormat (CFSTR_FILEDESCRIPTOR);
206
242
char name[101 ];
207
243
FORMATETC fmt;
208
244
while (formats->Next (1 , &fmt, nullptr ) == S_OK) {
@@ -211,6 +247,7 @@ bool DragDataProviderWin::contains(DragDataItemType type)
211
247
if (type == DragDataItemType::Paths)
212
248
return true ;
213
249
break ;
250
+ #if CLIP_ENABLE_IMAGE
214
251
case CF_DIBV5:
215
252
if (type == DragDataItemType::Image)
216
253
return true ;
@@ -219,13 +256,28 @@ bool DragDataProviderWin::contains(DragDataItemType type)
219
256
if (type == DragDataItemType::Image)
220
257
return true ;
221
258
break ;
259
+ #endif
222
260
default : {
223
261
switch (type) {
262
+ #if CLIP_ENABLE_IMAGE
224
263
case DragDataItemType::Image:
225
264
if (fmt.cfFormat == pngFormat)
226
265
return true ;
227
266
267
+ if (fmt.cfFormat == fileDescriptorFormat) {
268
+ DataWrapper data (m_data);
269
+ Medium<FILEGROUPDESCRIPTOR*> fgd = data.get <FILEGROUPDESCRIPTOR*>(fileDescriptorFormat);
270
+ if (fgd != nullptr && fgd->cItems > 0 ) {
271
+ std::string filename (base::to_utf8 (fgd->fgd ->cFileName ));
272
+ std::string ext = base::get_file_extension (filename);
273
+ std::transform (ext.begin (), ext.end (), ext.begin (), ::toupper);
274
+ if (ext == " PNG" || ext == " JPG" || ext == " JPEG" ||
275
+ ext == " JPE" || ext == " GIF" || ext == " BMP" )
276
+ return true ;
277
+ }
278
+ }
228
279
break ;
280
+ #endif
229
281
case DragDataItemType::Url:
230
282
if (fmt.cfFormat == urlFormat)
231
283
return true ;
0 commit comments