Index: ui/base/dragdrop/os_exchange_data_provider_win.cc |
diff --git a/ui/base/dragdrop/os_exchange_data_provider_win.cc b/ui/base/dragdrop/os_exchange_data_provider_win.cc |
index 4a2356992262e4a5a854da0d26bae531dda7f9d4..5be3a59237e8e1d29ec715e385a4753cbf5cc8e4 100644 |
--- a/ui/base/dragdrop/os_exchange_data_provider_win.cc |
+++ b/ui/base/dragdrop/os_exchange_data_provider_win.cc |
@@ -4,6 +4,9 @@ |
#include "ui/base/dragdrop/os_exchange_data_provider_win.h" |
+#include <objidl.h> |
+#include <shlobj.h> |
+#include <shobjidl.h> |
#include <stdint.h> |
#include <algorithm> |
@@ -16,12 +19,19 @@ |
#include "base/memory/ptr_util.h" |
#include "base/pickle.h" |
#include "base/strings/utf_string_conversions.h" |
+#include "base/win/scoped_comptr.h" |
+#include "base/win/scoped_hdc.h" |
#include "base/win/scoped_hglobal.h" |
#include "net/base/filename_util.h" |
+#include "skia/ext/skia_utils_win.h" |
+#include "third_party/skia/include/core/SkBitmap.h" |
#include "ui/base/clipboard/clipboard.h" |
#include "ui/base/clipboard/clipboard_util_win.h" |
#include "ui/base/dragdrop/file_info.h" |
#include "ui/base/l10n/l10n_util.h" |
+#include "ui/gfx/geometry/point.h" |
+#include "ui/gfx/image/image_skia.h" |
+#include "ui/gfx/skbitmap_operations.h" |
#include "ui/strings/grit/ui_strings.h" |
#include "url/gurl.h" |
@@ -540,18 +550,70 @@ void OSExchangeDataProviderWin::SetDownloadFileInfo( |
} |
void OSExchangeDataProviderWin::SetDragImage( |
- const gfx::ImageSkia& image, |
+ const gfx::ImageSkia& image_skia, |
const gfx::Vector2d& cursor_offset) { |
- drag_image_ = image; |
- drag_image_offset_ = cursor_offset; |
-} |
+ DCHECK(!image_skia.size().IsEmpty()); |
+ |
+ // InitializeFromBitmap() doesn't expect an alpha channel and is confused |
+ // by premultiplied colors, so unpremultiply the bitmap. |
+ SkBitmap unpremul_bitmap = |
+ SkBitmapOperations::UnPreMultiply(*image_skia.bitmap()); |
+ int width = unpremul_bitmap.width(); |
+ int height = unpremul_bitmap.height(); |
+ size_t rowbytes = unpremul_bitmap.rowBytes(); |
+ DCHECK_EQ(rowbytes, static_cast<size_t>(width) * 4u); |
+ |
+ void* bits; |
+ HBITMAP hbitmap; |
+ { |
+ BITMAPINFOHEADER header; |
+ skia::CreateBitmapHeader(width, height, &header); |
+ |
+ base::win::ScopedGetDC screen_dc(NULL); |
+ // By giving a null hSection, the |bits| will be destroyed when the |
+ // |hbitmap| is destroyed. |
+ hbitmap = |
+ CreateDIBSection(screen_dc, reinterpret_cast<BITMAPINFO*>(&header), |
+ DIB_RGB_COLORS, &bits, NULL, 0); |
+ } |
+ if (!hbitmap) |
+ return; |
-const gfx::ImageSkia& OSExchangeDataProviderWin::GetDragImage() const { |
- return drag_image_; |
-} |
+ { |
+ SkAutoLockPixels lock(unpremul_bitmap); |
+ memcpy(bits, unpremul_bitmap.getPixels(), height * rowbytes); |
+ } |
+ |
+ base::win::ScopedComPtr<IDragSourceHelper> helper; |
+ HRESULT rv = CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER, |
+ IID_IDragSourceHelper, helper.ReceiveVoid()); |
+ if (!SUCCEEDED(rv)) |
+ return; |
-const gfx::Vector2d& OSExchangeDataProviderWin::GetDragImageOffset() const { |
- return drag_image_offset_; |
+ // InitializeFromBitmap() takes ownership of |hbitmap|. |
+ SHDRAGIMAGE sdi; |
+ sdi.sizeDragImage.cx = width; |
+ sdi.sizeDragImage.cy = height; |
+ sdi.crColorKey = 0xFFFFFFFF; |
+ sdi.hbmpDragImage = hbitmap; |
+ sdi.ptOffset = gfx::PointAtOffsetFromOrigin(cursor_offset).ToPOINT(); |
+ helper->InitializeFromBitmap(&sdi, data_object()); |
+} |
+ |
+gfx::ImageSkia OSExchangeDataProviderWin::GetDragImage() const { |
+ // This class sets the image on data_object() so it shouldn't be used in |
+ // situations where the drag image is later queried. In that case a different |
+ // OSExchangeData::Provider should be used. |
+ NOTREACHED(); |
+ return gfx::ImageSkia(); |
+} |
+ |
+gfx::Vector2d OSExchangeDataProviderWin::GetDragImageOffset() const { |
+ // This class sets the image on data_object() so it shouldn't be used in |
+ // situations where the drag image is later queried. In that case a different |
+ // OSExchangeData::Provider should be used. |
+ NOTREACHED(); |
+ return gfx::Vector2d(); |
} |
/////////////////////////////////////////////////////////////////////////////// |