1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "views/drag_utils.h"
11 #include "base/win/scoped_comptr.h"
12 #include "ui/base/dragdrop/os_exchange_data.h"
13 #include "third_party/skia/include/core/SkBitmap.h"
14 #include "ui/base/dragdrop/os_exchange_data_provider_win.h"
15 #include "ui/gfx/canvas_skia.h"
16 #include "ui/gfx/gdi_util.h"
17 #include "ui/gfx/skbitmap_operations.h"
19 using ui::OSExchangeData
;
20 using ui::OSExchangeDataProviderWin
;
22 namespace drag_utils
{
24 static void SetDragImageOnDataObject(HBITMAP hbitmap
,
25 const gfx::Size
& size
,
26 const gfx::Point
& cursor_offset
,
27 IDataObject
* data_object
) {
28 base::win::ScopedComPtr
<IDragSourceHelper
> helper
;
29 HRESULT rv
= CoCreateInstance(CLSID_DragDropHelper
, 0, CLSCTX_INPROC_SERVER
,
30 IID_IDragSourceHelper
, helper
.ReceiveVoid());
33 sdi
.sizeDragImage
= size
.ToSIZE();
34 sdi
.crColorKey
= 0xFFFFFFFF;
35 sdi
.hbmpDragImage
= hbitmap
;
36 sdi
.ptOffset
= cursor_offset
.ToPOINT();
37 helper
->InitializeFromBitmap(&sdi
, data_object
);
41 // Blit the contents of the canvas to a new HBITMAP. It is the caller's
42 // responsibility to release the |bits| buffer.
43 static HBITMAP
CreateHBITMAPFromSkBitmap(const SkBitmap
& sk_bitmap
) {
44 HDC screen_dc
= GetDC(NULL
);
45 BITMAPINFOHEADER header
;
46 gfx::CreateBitmapHeader(sk_bitmap
.width(), sk_bitmap
.height(), &header
);
49 CreateDIBSection(screen_dc
, reinterpret_cast<BITMAPINFO
*>(&header
),
50 DIB_RGB_COLORS
, &bits
, NULL
, 0);
51 DCHECK(sk_bitmap
.rowBytes() == sk_bitmap
.width() * 4);
52 SkAutoLockPixels
lock(sk_bitmap
);
54 bits
, sk_bitmap
.getPixels(), sk_bitmap
.height() * sk_bitmap
.rowBytes());
55 ReleaseDC(NULL
, screen_dc
);
59 void SetDragImageOnDataObject(const SkBitmap
& sk_bitmap
,
60 const gfx::Size
& size
,
61 const gfx::Point
& cursor_offset
,
62 OSExchangeData
* data_object
) {
63 DCHECK(data_object
&& !size
.IsEmpty());
64 // InitializeFromBitmap() doesn't expect an alpha channel and is confused
65 // by premultiplied colors, so unpremultiply the bitmap.
66 // SetDragImageOnDataObject(HBITMAP) takes ownership of the bitmap.
67 HBITMAP bitmap
= CreateHBITMAPFromSkBitmap(
68 SkBitmapOperations::UnPreMultiply(sk_bitmap
));
70 // Attach 'bitmap' to the data_object.
71 SetDragImageOnDataObject(bitmap
, size
, cursor_offset
,
72 OSExchangeDataProviderWin::GetIDataObject(*data_object
));
75 } // namespace drag_utils