Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Side by Side Diff: base/clipboard_win.cc

Issue 260003: Move the clipboard stuff out of base and into app/clipboard. I renamed... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/clipboard_util.cc ('k') | base/scoped_clipboard_writer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2006-2008 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.
4
5 // Many of these functions are based on those found in
6 // webkit/port/platform/PasteboardWin.cpp
7
8 #include "base/clipboard.h"
9
10 #include <shlobj.h>
11 #include <shellapi.h>
12
13 #include "base/clipboard_util.h"
14 #include "base/file_path.h"
15 #include "base/gfx/size.h"
16 #include "base/lock.h"
17 #include "base/logging.h"
18 #include "base/message_loop.h"
19 #include "base/shared_memory.h"
20 #include "base/string_util.h"
21
22 namespace {
23
24 // A scoper to manage acquiring and automatically releasing the clipboard.
25 class ScopedClipboard {
26 public:
27 ScopedClipboard() : opened_(false) { }
28
29 ~ScopedClipboard() {
30 if (opened_)
31 Release();
32 }
33
34 bool Acquire(HWND owner) {
35 const int kMaxAttemptsToOpenClipboard = 5;
36
37 if (opened_) {
38 NOTREACHED();
39 return false;
40 }
41
42 // Attempt to open the clipboard, which will acquire the Windows clipboard
43 // lock. This may fail if another process currently holds this lock.
44 // We're willing to try a few times in the hopes of acquiring it.
45 //
46 // This turns out to be an issue when using remote desktop because the
47 // rdpclip.exe process likes to read what we've written to the clipboard and
48 // send it to the RDP client. If we open and close the clipboard in quick
49 // succession, we might be trying to open it while rdpclip.exe has it open,
50 // See Bug 815425.
51 //
52 // In fact, we believe we'll only spin this loop over remote desktop. In
53 // normal situations, the user is initiating clipboard operations and there
54 // shouldn't be contention.
55
56 for (int attempts = 0; attempts < kMaxAttemptsToOpenClipboard; ++attempts) {
57 // If we didn't manage to open the clipboard, sleep a bit and be hopeful.
58 if (attempts != 0)
59 ::Sleep(5);
60
61 if (::OpenClipboard(owner)) {
62 opened_ = true;
63 return true;
64 }
65 }
66
67 // We failed to acquire the clipboard.
68 return false;
69 }
70
71 void Release() {
72 if (opened_) {
73 ::CloseClipboard();
74 opened_ = false;
75 } else {
76 NOTREACHED();
77 }
78 }
79
80 private:
81 bool opened_;
82 };
83
84 LRESULT CALLBACK ClipboardOwnerWndProc(HWND hwnd,
85 UINT message,
86 WPARAM wparam,
87 LPARAM lparam) {
88 LRESULT lresult = 0;
89
90 switch (message) {
91 case WM_RENDERFORMAT:
92 // This message comes when SetClipboardData was sent a null data handle
93 // and now it's come time to put the data on the clipboard.
94 // We always set data, so there isn't a need to actually do anything here.
95 break;
96 case WM_RENDERALLFORMATS:
97 // This message comes when SetClipboardData was sent a null data handle
98 // and now this application is about to quit, so it must put data on
99 // the clipboard before it exits.
100 // We always set data, so there isn't a need to actually do anything here.
101 break;
102 case WM_DRAWCLIPBOARD:
103 break;
104 case WM_DESTROY:
105 break;
106 case WM_CHANGECBCHAIN:
107 break;
108 default:
109 lresult = DefWindowProc(hwnd, message, wparam, lparam);
110 break;
111 }
112 return lresult;
113 }
114
115 template <typename charT>
116 HGLOBAL CreateGlobalData(const std::basic_string<charT>& str) {
117 HGLOBAL data =
118 ::GlobalAlloc(GMEM_MOVEABLE, ((str.size() + 1) * sizeof(charT)));
119 if (data) {
120 charT* raw_data = static_cast<charT*>(::GlobalLock(data));
121 memcpy(raw_data, str.data(), str.size() * sizeof(charT));
122 raw_data[str.size()] = '\0';
123 ::GlobalUnlock(data);
124 }
125 return data;
126 };
127
128 } // namespace
129
130 Clipboard::Clipboard() : create_window_(false) {
131 if (MessageLoop::current()->type() == MessageLoop::TYPE_UI) {
132 // Make a dummy HWND to be the clipboard's owner.
133 WNDCLASSEX wcex = {0};
134 wcex.cbSize = sizeof(WNDCLASSEX);
135 wcex.lpfnWndProc = ClipboardOwnerWndProc;
136 wcex.hInstance = GetModuleHandle(NULL);
137 wcex.lpszClassName = L"ClipboardOwnerWindowClass";
138 ::RegisterClassEx(&wcex);
139 create_window_ = true;
140 }
141
142 clipboard_owner_ = NULL;
143 }
144
145 Clipboard::~Clipboard() {
146 if (clipboard_owner_)
147 ::DestroyWindow(clipboard_owner_);
148 clipboard_owner_ = NULL;
149 }
150
151 void Clipboard::WriteObjects(const ObjectMap& objects) {
152 WriteObjects(objects, NULL);
153 }
154
155 void Clipboard::WriteObjects(const ObjectMap& objects,
156 base::ProcessHandle process) {
157 ScopedClipboard clipboard;
158 if (!clipboard.Acquire(GetClipboardWindow()))
159 return;
160
161 ::EmptyClipboard();
162
163 for (ObjectMap::const_iterator iter = objects.begin();
164 iter != objects.end(); ++iter) {
165 if (iter->first == CBF_SMBITMAP)
166 WriteBitmapFromSharedMemory(&(iter->second[0].front()),
167 &(iter->second[1].front()),
168 process);
169 else
170 DispatchObject(static_cast<ObjectType>(iter->first), iter->second);
171 }
172 }
173
174 void Clipboard::WriteText(const char* text_data, size_t text_len) {
175 string16 text;
176 UTF8ToUTF16(text_data, text_len, &text);
177 HGLOBAL glob = CreateGlobalData(text);
178
179 WriteToClipboard(CF_UNICODETEXT, glob);
180 }
181
182 void Clipboard::WriteHTML(const char* markup_data,
183 size_t markup_len,
184 const char* url_data,
185 size_t url_len) {
186 std::string markup(markup_data, markup_len);
187 std::string url;
188
189 if (url_len > 0)
190 url.assign(url_data, url_len);
191
192 std::string html_fragment = ClipboardUtil::HtmlToCFHtml(markup, url);
193 HGLOBAL glob = CreateGlobalData(html_fragment);
194
195 WriteToClipboard(StringToInt(GetHtmlFormatType()), glob);
196 }
197
198 void Clipboard::WriteBookmark(const char* title_data,
199 size_t title_len,
200 const char* url_data,
201 size_t url_len) {
202 std::string bookmark(title_data, title_len);
203 bookmark.append(1, L'\n');
204 bookmark.append(url_data, url_len);
205
206 string16 wide_bookmark = UTF8ToWide(bookmark);
207 HGLOBAL glob = CreateGlobalData(wide_bookmark);
208
209 WriteToClipboard(StringToInt(GetUrlWFormatType()), glob);
210 }
211
212 void Clipboard::WriteWebSmartPaste() {
213 DCHECK(clipboard_owner_);
214 ::SetClipboardData(StringToInt(GetWebKitSmartPasteFormatType()), NULL);
215 }
216
217 void Clipboard::WriteBitmap(const char* pixel_data, const char* size_data) {
218 const gfx::Size* size = reinterpret_cast<const gfx::Size*>(size_data);
219 HDC dc = ::GetDC(NULL);
220
221 // This doesn't actually cost us a memcpy when the bitmap comes from the
222 // renderer as we load it into the bitmap using setPixels which just sets a
223 // pointer. Someone has to memcpy it into GDI, it might as well be us here.
224
225 // TODO(darin): share data in gfx/bitmap_header.cc somehow
226 BITMAPINFO bm_info = {0};
227 bm_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
228 bm_info.bmiHeader.biWidth = size->width();
229 bm_info.bmiHeader.biHeight = -size->height(); // sets vertical orientation
230 bm_info.bmiHeader.biPlanes = 1;
231 bm_info.bmiHeader.biBitCount = 32;
232 bm_info.bmiHeader.biCompression = BI_RGB;
233
234 // ::CreateDIBSection allocates memory for us to copy our bitmap into.
235 // Unfortunately, we can't write the created bitmap to the clipboard,
236 // (see http://msdn2.microsoft.com/en-us/library/ms532292.aspx)
237 void *bits;
238 HBITMAP source_hbitmap =
239 ::CreateDIBSection(dc, &bm_info, DIB_RGB_COLORS, &bits, NULL, 0);
240
241 if (bits && source_hbitmap) {
242 // Copy the bitmap out of shared memory and into GDI
243 memcpy(bits, pixel_data, 4 * size->width() * size->height());
244
245 // Now we have an HBITMAP, we can write it to the clipboard
246 WriteBitmapFromHandle(source_hbitmap, *size);
247 }
248
249 ::DeleteObject(source_hbitmap);
250 ::ReleaseDC(NULL, dc);
251 }
252
253 void Clipboard::WriteBitmapFromSharedMemory(const char* bitmap_data,
254 const char* size_data,
255 base::ProcessHandle process) {
256 const gfx::Size* size = reinterpret_cast<const gfx::Size*>(size_data);
257
258 // bitmap_data has an encoded shared memory object. See
259 // DuplicateRemoteHandles().
260 char* ptr = const_cast<char*>(bitmap_data);
261 scoped_ptr<const base::SharedMemory> bitmap(*
262 reinterpret_cast<const base::SharedMemory**>(ptr));
263
264 // TODO(darin): share data in gfx/bitmap_header.cc somehow.
265 BITMAPINFO bm_info = {0};
266 bm_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
267 bm_info.bmiHeader.biWidth = size->width();
268 // Sets the vertical orientation.
269 bm_info.bmiHeader.biHeight = -size->height();
270 bm_info.bmiHeader.biPlanes = 1;
271 bm_info.bmiHeader.biBitCount = 32;
272 bm_info.bmiHeader.biCompression = BI_RGB;
273
274 HDC dc = ::GetDC(NULL);
275
276 // We can create an HBITMAP directly using the shared memory handle, saving
277 // a memcpy.
278 HBITMAP source_hbitmap =
279 ::CreateDIBSection(dc, &bm_info, DIB_RGB_COLORS, NULL,
280 bitmap->handle(), 0);
281
282 if (source_hbitmap) {
283 // Now we can write the HBITMAP to the clipboard
284 WriteBitmapFromHandle(source_hbitmap, *size);
285 }
286
287 ::DeleteObject(source_hbitmap);
288 ::ReleaseDC(NULL, dc);
289 }
290
291 void Clipboard::WriteBitmapFromHandle(HBITMAP source_hbitmap,
292 const gfx::Size& size) {
293 // We would like to just call ::SetClipboardData on the source_hbitmap,
294 // but that bitmap might not be of a sort we can write to the clipboard.
295 // For this reason, we create a new bitmap, copy the bits over, and then
296 // write that to the clipboard.
297
298 HDC dc = ::GetDC(NULL);
299 HDC compatible_dc = ::CreateCompatibleDC(NULL);
300 HDC source_dc = ::CreateCompatibleDC(NULL);
301
302 // This is the HBITMAP we will eventually write to the clipboard
303 HBITMAP hbitmap = ::CreateCompatibleBitmap(dc, size.width(), size.height());
304 if (!hbitmap) {
305 // Failed to create the bitmap
306 ::DeleteDC(compatible_dc);
307 ::DeleteDC(source_dc);
308 ::ReleaseDC(NULL, dc);
309 return;
310 }
311
312 HBITMAP old_hbitmap = (HBITMAP)SelectObject(compatible_dc, hbitmap);
313 HBITMAP old_source = (HBITMAP)SelectObject(source_dc, source_hbitmap);
314
315 // Now we need to blend it into an HBITMAP we can place on the clipboard
316 BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
317 ::GdiAlphaBlend(compatible_dc, 0, 0, size.width(), size.height(),
318 source_dc, 0, 0, size.width(), size.height(), bf);
319
320 // Clean up all the handles we just opened
321 ::SelectObject(compatible_dc, old_hbitmap);
322 ::SelectObject(source_dc, old_source);
323 ::DeleteObject(old_hbitmap);
324 ::DeleteObject(old_source);
325 ::DeleteDC(compatible_dc);
326 ::DeleteDC(source_dc);
327 ::ReleaseDC(NULL, dc);
328
329 WriteToClipboard(CF_BITMAP, hbitmap);
330 }
331
332 // Write a file or set of files to the clipboard in HDROP format. When the user
333 // invokes a paste command (in a Windows explorer shell, for example), the files
334 // will be copied to the paste location.
335 void Clipboard::WriteFiles(const char* file_data, size_t file_len) {
336 // Calculate the amount of space we'll need store the strings and
337 // a DROPFILES struct.
338 size_t bytes = sizeof(DROPFILES) + file_len;
339
340 HANDLE hdata = ::GlobalAlloc(GMEM_MOVEABLE, bytes);
341 if (!hdata)
342 return;
343
344 char* data = static_cast<char*>(::GlobalLock(hdata));
345 DROPFILES* drop_files = reinterpret_cast<DROPFILES*>(data);
346 drop_files->pFiles = sizeof(DROPFILES);
347 drop_files->fWide = TRUE;
348
349 memcpy(data + sizeof(DROPFILES), file_data, file_len);
350
351 ::GlobalUnlock(hdata);
352 WriteToClipboard(CF_HDROP, hdata);
353 }
354
355 void Clipboard::WriteData(const char* format_name, size_t format_len,
356 const char* data_data, size_t data_len) {
357 std::string format(format_name, format_len);
358 CLIPFORMAT clip_format =
359 ::RegisterClipboardFormat(ASCIIToWide(format).c_str());
360
361 HGLOBAL hdata = ::GlobalAlloc(GMEM_MOVEABLE, data_len);
362 if (!hdata)
363 return;
364
365 char* data = static_cast<char*>(::GlobalLock(hdata));
366 memcpy(data, data_data, data_len);
367 ::GlobalUnlock(data);
368 WriteToClipboard(clip_format, hdata);
369 }
370
371 void Clipboard::WriteToClipboard(unsigned int format, HANDLE handle) {
372 DCHECK(clipboard_owner_);
373 if (handle && !::SetClipboardData(format, handle)) {
374 DCHECK(ERROR_CLIPBOARD_NOT_OPEN != GetLastError());
375 FreeData(format, handle);
376 }
377 }
378
379 bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format,
380 Clipboard::Buffer buffer) const {
381 DCHECK_EQ(buffer, BUFFER_STANDARD);
382 return ::IsClipboardFormatAvailable(StringToInt(format)) != FALSE;
383 }
384
385 bool Clipboard::IsFormatAvailableByString(
386 const std::string& ascii_format, Clipboard::Buffer buffer) const {
387 DCHECK_EQ(buffer, BUFFER_STANDARD);
388 std::wstring wide_format = ASCIIToWide(ascii_format);
389 CLIPFORMAT format = ::RegisterClipboardFormat(wide_format.c_str());
390 return ::IsClipboardFormatAvailable(format) != FALSE;
391 }
392
393 void Clipboard::ReadText(Clipboard::Buffer buffer, string16* result) const {
394 DCHECK_EQ(buffer, BUFFER_STANDARD);
395 if (!result) {
396 NOTREACHED();
397 return;
398 }
399
400 result->clear();
401
402 // Acquire the clipboard.
403 ScopedClipboard clipboard;
404 if (!clipboard.Acquire(GetClipboardWindow()))
405 return;
406
407 HANDLE data = ::GetClipboardData(CF_UNICODETEXT);
408 if (!data)
409 return;
410
411 result->assign(static_cast<const char16*>(::GlobalLock(data)));
412 ::GlobalUnlock(data);
413 }
414
415 void Clipboard::ReadAsciiText(Clipboard::Buffer buffer,
416 std::string* result) const {
417 DCHECK_EQ(buffer, BUFFER_STANDARD);
418 if (!result) {
419 NOTREACHED();
420 return;
421 }
422
423 result->clear();
424
425 // Acquire the clipboard.
426 ScopedClipboard clipboard;
427 if (!clipboard.Acquire(GetClipboardWindow()))
428 return;
429
430 HANDLE data = ::GetClipboardData(CF_TEXT);
431 if (!data)
432 return;
433
434 result->assign(static_cast<const char*>(::GlobalLock(data)));
435 ::GlobalUnlock(data);
436 }
437
438 void Clipboard::ReadHTML(Clipboard::Buffer buffer, string16* markup,
439 std::string* src_url) const {
440 DCHECK_EQ(buffer, BUFFER_STANDARD);
441 if (markup)
442 markup->clear();
443
444 if (src_url)
445 src_url->clear();
446
447 // Acquire the clipboard.
448 ScopedClipboard clipboard;
449 if (!clipboard.Acquire(GetClipboardWindow()))
450 return;
451
452 HANDLE data = ::GetClipboardData(StringToInt(GetHtmlFormatType()));
453 if (!data)
454 return;
455
456 std::string html_fragment(static_cast<const char*>(::GlobalLock(data)));
457 ::GlobalUnlock(data);
458
459 std::string markup_utf8;
460 ClipboardUtil::CFHtmlToHtml(html_fragment, markup ? &markup_utf8 : NULL,
461 src_url);
462 if (markup)
463 markup->assign(UTF8ToWide(markup_utf8));
464 }
465
466 void Clipboard::ReadBookmark(string16* title, std::string* url) const {
467 if (title)
468 title->clear();
469
470 if (url)
471 url->clear();
472
473 // Acquire the clipboard.
474 ScopedClipboard clipboard;
475 if (!clipboard.Acquire(GetClipboardWindow()))
476 return;
477
478 HANDLE data = ::GetClipboardData(StringToInt(GetUrlWFormatType()));
479 if (!data)
480 return;
481
482 string16 bookmark(static_cast<const char16*>(::GlobalLock(data)));
483 ::GlobalUnlock(data);
484
485 ParseBookmarkClipboardFormat(bookmark, title, url);
486 }
487
488 // Read a file in HDROP format from the clipboard.
489 void Clipboard::ReadFile(FilePath* file) const {
490 if (!file) {
491 NOTREACHED();
492 return;
493 }
494
495 *file = FilePath();
496 std::vector<FilePath> files;
497 ReadFiles(&files);
498
499 // Take the first file, if available.
500 if (!files.empty())
501 *file = files[0];
502 }
503
504 // Read a set of files in HDROP format from the clipboard.
505 void Clipboard::ReadFiles(std::vector<FilePath>* files) const {
506 if (!files) {
507 NOTREACHED();
508 return;
509 }
510
511 files->clear();
512
513 ScopedClipboard clipboard;
514 if (!clipboard.Acquire(GetClipboardWindow()))
515 return;
516
517 HDROP drop = static_cast<HDROP>(::GetClipboardData(CF_HDROP));
518 if (!drop)
519 return;
520
521 // Count of files in the HDROP.
522 int count = ::DragQueryFile(drop, 0xffffffff, NULL, 0);
523
524 if (count) {
525 for (int i = 0; i < count; ++i) {
526 int size = ::DragQueryFile(drop, i, NULL, 0) + 1;
527 std::wstring file;
528 ::DragQueryFile(drop, i, WriteInto(&file, size), size);
529 files->push_back(FilePath(file));
530 }
531 }
532 }
533
534 void Clipboard::ReadData(const std::string& format, std::string* result) {
535 if (!result) {
536 NOTREACHED();
537 return;
538 }
539
540 CLIPFORMAT clip_format =
541 ::RegisterClipboardFormat(ASCIIToWide(format).c_str());
542
543 ScopedClipboard clipboard;
544 if (!clipboard.Acquire(GetClipboardWindow()))
545 return;
546
547 HANDLE data = ::GetClipboardData(clip_format);
548 if (!data)
549 return;
550
551 result->assign(static_cast<const char*>(::GlobalLock(data)),
552 ::GlobalSize(data));
553 ::GlobalUnlock(data);
554 }
555
556 // static
557 void Clipboard::ParseBookmarkClipboardFormat(const string16& bookmark,
558 string16* title,
559 std::string* url) {
560 const string16 kDelim = ASCIIToUTF16("\r\n");
561
562 const size_t title_end = bookmark.find_first_of(kDelim);
563 if (title)
564 title->assign(bookmark.substr(0, title_end));
565
566 if (url) {
567 const size_t url_start = bookmark.find_first_not_of(kDelim, title_end);
568 if (url_start != string16::npos)
569 *url = UTF16ToUTF8(bookmark.substr(url_start, string16::npos));
570 }
571 }
572
573 // static
574 Clipboard::FormatType Clipboard::GetUrlFormatType() {
575 return IntToString(ClipboardUtil::GetUrlFormat()->cfFormat);
576 }
577
578 // static
579 Clipboard::FormatType Clipboard::GetUrlWFormatType() {
580 return IntToString(ClipboardUtil::GetUrlWFormat()->cfFormat);
581 }
582
583 // static
584 Clipboard::FormatType Clipboard::GetMozUrlFormatType() {
585 return IntToString(ClipboardUtil::GetMozUrlFormat()->cfFormat);
586 }
587
588 // static
589 Clipboard::FormatType Clipboard::GetPlainTextFormatType() {
590 return IntToString(ClipboardUtil::GetPlainTextFormat()->cfFormat);
591 }
592
593 // static
594 Clipboard::FormatType Clipboard::GetPlainTextWFormatType() {
595 return IntToString(ClipboardUtil::GetPlainTextWFormat()->cfFormat);
596 }
597
598 // static
599 Clipboard::FormatType Clipboard::GetFilenameFormatType() {
600 return IntToString(ClipboardUtil::GetFilenameFormat()->cfFormat);
601 }
602
603 // static
604 Clipboard::FormatType Clipboard::GetFilenameWFormatType() {
605 return IntToString(ClipboardUtil::GetFilenameWFormat()->cfFormat);
606 }
607
608 // MS HTML Format
609 // static
610 Clipboard::FormatType Clipboard::GetHtmlFormatType() {
611 return IntToString(ClipboardUtil::GetHtmlFormat()->cfFormat);
612 }
613
614 // static
615 Clipboard::FormatType Clipboard::GetBitmapFormatType() {
616 return IntToString(CF_BITMAP);
617 }
618
619 // Firefox text/html
620 // static
621 Clipboard::FormatType Clipboard::GetTextHtmlFormatType() {
622 return IntToString(ClipboardUtil::GetTextHtmlFormat()->cfFormat);
623 }
624
625 // static
626 Clipboard::FormatType Clipboard::GetCFHDropFormatType() {
627 return IntToString(ClipboardUtil::GetCFHDropFormat()->cfFormat);
628 }
629
630 // static
631 Clipboard::FormatType Clipboard::GetFileDescriptorFormatType() {
632 return IntToString(ClipboardUtil::GetFileDescriptorFormat()->cfFormat);
633 }
634
635 // static
636 Clipboard::FormatType Clipboard::GetFileContentFormatZeroType() {
637 return IntToString(ClipboardUtil::GetFileContentFormatZero()->cfFormat);
638 }
639
640 // static
641 void Clipboard::DuplicateRemoteHandles(base::ProcessHandle process,
642 ObjectMap* objects) {
643 for (ObjectMap::iterator iter = objects->begin(); iter != objects->end();
644 ++iter) {
645 if (iter->first == CBF_SMBITMAP) {
646 // There is a shared memory handle encoded on the first ObjectMapParam.
647 // Use it to open a local handle to the memory.
648 char* bitmap_data = &(iter->second[0].front());
649 base::SharedMemoryHandle* remote_bitmap_handle =
650 reinterpret_cast<base::SharedMemoryHandle*>(bitmap_data);
651
652 base::SharedMemory* bitmap = new base::SharedMemory(*remote_bitmap_handle,
653 false, process);
654
655 // We store the object where the remote handle was located so it can
656 // be retrieved by the UI thread (see WriteBitmapFromSharedMemory()).
657 iter->second[0].clear();
658 for (size_t i = 0; i < sizeof(bitmap); i++)
659 iter->second[0].push_back(reinterpret_cast<char*>(&bitmap)[i]);
660 }
661 }
662 }
663
664 // static
665 Clipboard::FormatType Clipboard::GetWebKitSmartPasteFormatType() {
666 return IntToString(ClipboardUtil::GetWebKitSmartPasteFormat()->cfFormat);
667 }
668
669 // static
670 void Clipboard::FreeData(unsigned int format, HANDLE data) {
671 if (format == CF_BITMAP)
672 ::DeleteObject(static_cast<HBITMAP>(data));
673 else
674 ::GlobalFree(data);
675 }
676
677 HWND Clipboard::GetClipboardWindow() const {
678 if (!clipboard_owner_ && create_window_) {
679 clipboard_owner_ = ::CreateWindow(L"ClipboardOwnerWindowClass",
680 L"ClipboardOwnerWindow",
681 0, 0, 0, 0, 0,
682 HWND_MESSAGE,
683 0, 0, 0);
684 }
685 return clipboard_owner_;
686 }
OLDNEW
« no previous file with comments | « base/clipboard_util.cc ('k') | base/scoped_clipboard_writer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698