1 /*
2 * barrier -- mouse and keyboard sharing utility
3 * Copyright (C) 2012-2016 Symless Ltd.
4 * Copyright (C) 2004 Chris Schoeneman
5 *
6 * This package is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * found in the file LICENSE that should have accompanied this file.
9 *
10 * This package is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "platform/MSWindowsClipboardBitmapConverter.h"
20
21 #include "base/Log.h"
22
23 //
24 // MSWindowsClipboardBitmapConverter
25 //
26
MSWindowsClipboardBitmapConverter()27 MSWindowsClipboardBitmapConverter::MSWindowsClipboardBitmapConverter()
28 {
29 // do nothing
30 }
31
~MSWindowsClipboardBitmapConverter()32 MSWindowsClipboardBitmapConverter::~MSWindowsClipboardBitmapConverter()
33 {
34 // do nothing
35 }
36
37 IClipboard::EFormat
getFormat() const38 MSWindowsClipboardBitmapConverter::getFormat() const
39 {
40 return IClipboard::kBitmap;
41 }
42
43 UINT
getWin32Format() const44 MSWindowsClipboardBitmapConverter::getWin32Format() const
45 {
46 return CF_DIB;
47 }
48
fromIClipboard(const std::string & data) const49 HANDLE MSWindowsClipboardBitmapConverter::fromIClipboard(const std::string& data) const
50 {
51 // copy to memory handle
52 HGLOBAL gData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, data.size());
53 if (gData != NULL) {
54 // get a pointer to the allocated memory
55 char* dst = (char*)GlobalLock(gData);
56 if (dst != NULL) {
57 memcpy(dst, data.data(), data.size());
58 GlobalUnlock(gData);
59 }
60 else {
61 GlobalFree(gData);
62 gData = NULL;
63 }
64 }
65
66 return gData;
67 }
68
toIClipboard(HANDLE data) const69 std::string MSWindowsClipboardBitmapConverter::toIClipboard(HANDLE data) const
70 {
71 // get datator
72 LPVOID src = GlobalLock(data);
73 if (src == NULL) {
74 return {};
75 }
76 UInt32 srcSize = (UInt32)GlobalSize(data);
77
78 // check image type
79 const BITMAPINFO* bitmap = static_cast<const BITMAPINFO*>(src);
80 LOG((CLOG_INFO "bitmap: %dx%d %d", bitmap->bmiHeader.biWidth, bitmap->bmiHeader.biHeight, (int)bitmap->bmiHeader.biBitCount));
81 if (bitmap->bmiHeader.biPlanes == 1 &&
82 (bitmap->bmiHeader.biBitCount == 24 ||
83 bitmap->bmiHeader.biBitCount == 32) &&
84 bitmap->bmiHeader.biCompression == BI_RGB) {
85 // already in canonical form
86 std::string image(static_cast<char const*>(src), srcSize);
87 GlobalUnlock(data);
88 return image;
89 }
90
91 // create a destination DIB section
92 LOG((CLOG_INFO "convert image from: depth=%d comp=%d", bitmap->bmiHeader.biBitCount, bitmap->bmiHeader.biCompression));
93 void* raw;
94 BITMAPINFOHEADER info;
95 LONG w = bitmap->bmiHeader.biWidth;
96 LONG h = bitmap->bmiHeader.biHeight;
97 info.biSize = sizeof(BITMAPINFOHEADER);
98 info.biWidth = w;
99 info.biHeight = h;
100 info.biPlanes = 1;
101 info.biBitCount = 32;
102 info.biCompression = BI_RGB;
103 info.biSizeImage = 0;
104 info.biXPelsPerMeter = 1000;
105 info.biYPelsPerMeter = 1000;
106 info.biClrUsed = 0;
107 info.biClrImportant = 0;
108 HDC dc = GetDC(NULL);
109 HBITMAP dst = CreateDIBSection(dc, (BITMAPINFO*)&info,
110 DIB_RGB_COLORS, &raw, NULL, 0);
111
112 // find the start of the pixel data
113 const char* srcBits = (const char*)bitmap + bitmap->bmiHeader.biSize;
114 if (bitmap->bmiHeader.biBitCount >= 16) {
115 if (bitmap->bmiHeader.biCompression == BI_BITFIELDS &&
116 (bitmap->bmiHeader.biBitCount == 16 ||
117 bitmap->bmiHeader.biBitCount == 32)) {
118 srcBits += 3 * sizeof(DWORD);
119 }
120 }
121 else if (bitmap->bmiHeader.biClrUsed != 0) {
122 srcBits += bitmap->bmiHeader.biClrUsed * sizeof(RGBQUAD);
123 }
124 else {
125 //http://msdn.microsoft.com/en-us/library/ke55d167(VS.80).aspx
126 srcBits += (1i64 << bitmap->bmiHeader.biBitCount) * sizeof(RGBQUAD);
127 }
128
129 // copy source image to destination image
130 HDC dstDC = CreateCompatibleDC(dc);
131 HGDIOBJ oldBitmap = SelectObject(dstDC, dst);
132 SetDIBitsToDevice(dstDC, 0, 0, w, h, 0, 0, 0, h,
133 srcBits, bitmap, DIB_RGB_COLORS);
134 SelectObject(dstDC, oldBitmap);
135 DeleteDC(dstDC);
136 GdiFlush();
137
138 // extract data
139 std::string image((const char*)&info, info.biSize);
140 image.append((const char*)raw, 4 * w * h);
141
142 // clean up GDI
143 DeleteObject(dst);
144 ReleaseDC(NULL, dc);
145
146 // release handle
147 GlobalUnlock(data);
148
149 return image;
150 }
151