OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Many of these functions are based on those found in | 5 // Many of these functions are based on those found in |
6 // webkit/port/platform/PasteboardWin.cpp | 6 // webkit/port/platform/PasteboardWin.cpp |
7 | 7 |
8 #include "ui/base/clipboard/clipboard.h" | 8 #include "ui/base/clipboard/clipboard_win.h" |
9 | 9 |
10 #include <shellapi.h> | 10 #include <shellapi.h> |
11 #include <shlobj.h> | 11 #include <shlobj.h> |
12 | 12 |
13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
14 #include "base/bind.h" | 14 #include "base/bind.h" |
15 #include "base/files/file_path.h" | 15 #include "base/files/file_path.h" |
16 #include "base/logging.h" | 16 #include "base/logging.h" |
17 #include "base/memory/shared_memory.h" | 17 #include "base/memory/shared_memory.h" |
18 #include "base/message_loop/message_loop.h" | 18 #include "base/message_loop/message_loop.h" |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 } | 152 } |
153 | 153 |
154 void MakeBitmapOpaque(const SkBitmap& bitmap) { | 154 void MakeBitmapOpaque(const SkBitmap& bitmap) { |
155 for (int x = 0; x < bitmap.width(); ++x) { | 155 for (int x = 0; x < bitmap.width(); ++x) { |
156 for (int y = 0; y < bitmap.height(); ++y) { | 156 for (int y = 0; y < bitmap.height(); ++y) { |
157 *bitmap.getAddr32(x, y) = SkColorSetA(*bitmap.getAddr32(x, y), 0xFF); | 157 *bitmap.getAddr32(x, y) = SkColorSetA(*bitmap.getAddr32(x, y), 0xFF); |
158 } | 158 } |
159 } | 159 } |
160 } | 160 } |
161 | 161 |
| 162 void ParseBookmarkClipboardFormat(const base::string16& bookmark, |
| 163 base::string16* title, |
| 164 std::string* url) { |
| 165 const base::string16 kDelim = base::ASCIIToUTF16("\r\n"); |
| 166 |
| 167 const size_t title_end = bookmark.find_first_of(kDelim); |
| 168 if (title) |
| 169 title->assign(bookmark.substr(0, title_end)); |
| 170 |
| 171 if (url) { |
| 172 const size_t url_start = bookmark.find_first_not_of(kDelim, title_end); |
| 173 if (url_start != base::string16::npos) { |
| 174 *url = |
| 175 base::UTF16ToUTF8(bookmark.substr(url_start, base::string16::npos)); |
| 176 } |
| 177 } |
| 178 } |
| 179 |
| 180 void FreeData(unsigned int format, HANDLE data) { |
| 181 if (format == CF_BITMAP) |
| 182 ::DeleteObject(static_cast<HBITMAP>(data)); |
| 183 else |
| 184 ::GlobalFree(data); |
| 185 } |
| 186 |
162 } // namespace | 187 } // namespace |
163 | 188 |
164 // Clipboard::FormatType implementation. | 189 // Clipboard::FormatType implementation. |
165 Clipboard::FormatType::FormatType() : data_() {} | 190 Clipboard::FormatType::FormatType() : data_() {} |
166 | 191 |
167 Clipboard::FormatType::FormatType(UINT native_format) : data_() { | 192 Clipboard::FormatType::FormatType(UINT native_format) : data_() { |
168 // There's no good way to actually initialize this in the constructor in | 193 // There's no good way to actually initialize this in the constructor in |
169 // C++03. | 194 // C++03. |
170 data_.cfFormat = native_format; | 195 data_.cfFormat = native_format; |
171 data_.dwAspect = DVASPECT_CONTENT; | 196 data_.dwAspect = DVASPECT_CONTENT; |
(...skipping 22 matching lines...) Expand all Loading... |
194 const std::string& serialization) { | 219 const std::string& serialization) { |
195 int clipboard_format = -1; | 220 int clipboard_format = -1; |
196 if (!base::StringToInt(serialization, &clipboard_format)) { | 221 if (!base::StringToInt(serialization, &clipboard_format)) { |
197 NOTREACHED(); | 222 NOTREACHED(); |
198 return FormatType(); | 223 return FormatType(); |
199 } | 224 } |
200 return FormatType(clipboard_format); | 225 return FormatType(clipboard_format); |
201 } | 226 } |
202 | 227 |
203 bool Clipboard::FormatType::operator<(const FormatType& other) const { | 228 bool Clipboard::FormatType::operator<(const FormatType& other) const { |
204 return ToUINT() < other.ToUINT(); | 229 return data_.cfFormat < other.data_.cfFormat; |
205 } | 230 } |
206 | 231 |
207 bool Clipboard::FormatType::Equals(const FormatType& other) const { | 232 bool Clipboard::FormatType::Equals(const FormatType& other) const { |
208 return ToUINT() == other.ToUINT(); | 233 return data_.cfFormat == other.data_.cfFormat; |
209 } | 234 } |
210 | 235 |
211 // Various predefined FormatTypes. | 236 // Various predefined FormatTypes. |
212 // static | 237 // static |
213 Clipboard::FormatType Clipboard::GetFormatType( | 238 Clipboard::FormatType Clipboard::GetFormatType( |
214 const std::string& format_string) { | 239 const std::string& format_string) { |
215 return FormatType( | 240 return FormatType( |
216 ::RegisterClipboardFormat(base::ASCIIToWide(format_string).c_str())); | 241 ::RegisterClipboardFormat(base::ASCIIToWide(format_string).c_str())); |
217 } | 242 } |
218 | 243 |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
341 | 366 |
342 // static | 367 // static |
343 const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() { | 368 const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() { |
344 CR_DEFINE_STATIC_LOCAL( | 369 CR_DEFINE_STATIC_LOCAL( |
345 FormatType, | 370 FormatType, |
346 type, | 371 type, |
347 (::RegisterClipboardFormat(L"Chromium Pepper MIME Data Format"))); | 372 (::RegisterClipboardFormat(L"Chromium Pepper MIME Data Format"))); |
348 return type; | 373 return type; |
349 } | 374 } |
350 | 375 |
351 // Clipboard implementation. | 376 // Clipboard factory method. |
352 Clipboard::Clipboard() { | 377 // static |
| 378 Clipboard* Clipboard::Create() { |
| 379 return new ClipboardWin; |
| 380 } |
| 381 |
| 382 // ClipboardWin implementation. |
| 383 ClipboardWin::ClipboardWin() { |
353 if (base::MessageLoopForUI::IsCurrent()) | 384 if (base::MessageLoopForUI::IsCurrent()) |
354 clipboard_owner_.reset(new base::win::MessageWindow()); | 385 clipboard_owner_.reset(new base::win::MessageWindow()); |
355 } | 386 } |
356 | 387 |
357 Clipboard::~Clipboard() { | 388 ClipboardWin::~ClipboardWin() { |
358 } | 389 } |
359 | 390 |
360 uint64 Clipboard::GetSequenceNumber(ClipboardType type) { | 391 uint64 ClipboardWin::GetSequenceNumber(ClipboardType type) { |
361 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); | 392 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); |
362 return ::GetClipboardSequenceNumber(); | 393 return ::GetClipboardSequenceNumber(); |
363 } | 394 } |
364 | 395 |
365 bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format, | 396 bool ClipboardWin::IsFormatAvailable(const Clipboard::FormatType& format, |
366 ClipboardType type) const { | 397 ClipboardType type) const { |
367 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); | 398 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); |
368 return ::IsClipboardFormatAvailable(format.ToUINT()) != FALSE; | 399 return ::IsClipboardFormatAvailable(format.ToFormatEtc().cfFormat) != FALSE; |
369 } | 400 } |
370 | 401 |
371 void Clipboard::Clear(ClipboardType type) { | 402 void ClipboardWin::Clear(ClipboardType type) { |
372 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); | 403 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); |
373 ScopedClipboard clipboard; | 404 ScopedClipboard clipboard; |
374 if (!clipboard.Acquire(GetClipboardWindow())) | 405 if (!clipboard.Acquire(GetClipboardWindow())) |
375 return; | 406 return; |
376 | 407 |
377 ::EmptyClipboard(); | 408 ::EmptyClipboard(); |
378 } | 409 } |
379 | 410 |
380 void Clipboard::ReadAvailableTypes(ClipboardType type, | 411 void ClipboardWin::ReadAvailableTypes(ClipboardType type, |
381 std::vector<base::string16>* types, | 412 std::vector<base::string16>* types, |
382 bool* contains_filenames) const { | 413 bool* contains_filenames) const { |
383 if (!types || !contains_filenames) { | 414 if (!types || !contains_filenames) { |
384 NOTREACHED(); | 415 NOTREACHED(); |
385 return; | 416 return; |
386 } | 417 } |
387 | 418 |
388 types->clear(); | 419 types->clear(); |
389 if (::IsClipboardFormatAvailable(GetPlainTextFormatType().ToUINT())) | 420 if (::IsClipboardFormatAvailable( |
| 421 GetPlainTextFormatType().ToFormatEtc().cfFormat)) |
390 types->push_back(base::UTF8ToUTF16(kMimeTypeText)); | 422 types->push_back(base::UTF8ToUTF16(kMimeTypeText)); |
391 if (::IsClipboardFormatAvailable(GetHtmlFormatType().ToUINT())) | 423 if (::IsClipboardFormatAvailable(GetHtmlFormatType().ToFormatEtc().cfFormat)) |
392 types->push_back(base::UTF8ToUTF16(kMimeTypeHTML)); | 424 types->push_back(base::UTF8ToUTF16(kMimeTypeHTML)); |
393 if (::IsClipboardFormatAvailable(GetRtfFormatType().ToUINT())) | 425 if (::IsClipboardFormatAvailable(GetRtfFormatType().ToFormatEtc().cfFormat)) |
394 types->push_back(base::UTF8ToUTF16(kMimeTypeRTF)); | 426 types->push_back(base::UTF8ToUTF16(kMimeTypeRTF)); |
395 if (::IsClipboardFormatAvailable(CF_DIB)) | 427 if (::IsClipboardFormatAvailable(CF_DIB)) |
396 types->push_back(base::UTF8ToUTF16(kMimeTypePNG)); | 428 types->push_back(base::UTF8ToUTF16(kMimeTypePNG)); |
397 *contains_filenames = false; | 429 *contains_filenames = false; |
398 | 430 |
399 // Acquire the clipboard. | 431 // Acquire the clipboard. |
400 ScopedClipboard clipboard; | 432 ScopedClipboard clipboard; |
401 if (!clipboard.Acquire(GetClipboardWindow())) | 433 if (!clipboard.Acquire(GetClipboardWindow())) |
402 return; | 434 return; |
403 | 435 |
404 HANDLE hdata = ::GetClipboardData(GetWebCustomDataFormatType().ToUINT()); | 436 HANDLE hdata = |
| 437 ::GetClipboardData(GetWebCustomDataFormatType().ToFormatEtc().cfFormat); |
405 if (!hdata) | 438 if (!hdata) |
406 return; | 439 return; |
407 | 440 |
408 ReadCustomDataTypes(::GlobalLock(hdata), ::GlobalSize(hdata), types); | 441 ReadCustomDataTypes(::GlobalLock(hdata), ::GlobalSize(hdata), types); |
409 ::GlobalUnlock(hdata); | 442 ::GlobalUnlock(hdata); |
410 } | 443 } |
411 | 444 |
412 void Clipboard::ReadText(ClipboardType type, base::string16* result) const { | 445 void ClipboardWin::ReadText(ClipboardType type, base::string16* result) const { |
413 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); | 446 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); |
414 if (!result) { | 447 if (!result) { |
415 NOTREACHED(); | 448 NOTREACHED(); |
416 return; | 449 return; |
417 } | 450 } |
418 | 451 |
419 result->clear(); | 452 result->clear(); |
420 | 453 |
421 // Acquire the clipboard. | 454 // Acquire the clipboard. |
422 ScopedClipboard clipboard; | 455 ScopedClipboard clipboard; |
423 if (!clipboard.Acquire(GetClipboardWindow())) | 456 if (!clipboard.Acquire(GetClipboardWindow())) |
424 return; | 457 return; |
425 | 458 |
426 HANDLE data = ::GetClipboardData(CF_UNICODETEXT); | 459 HANDLE data = ::GetClipboardData(CF_UNICODETEXT); |
427 if (!data) | 460 if (!data) |
428 return; | 461 return; |
429 | 462 |
430 result->assign(static_cast<const base::char16*>(::GlobalLock(data))); | 463 result->assign(static_cast<const base::char16*>(::GlobalLock(data))); |
431 ::GlobalUnlock(data); | 464 ::GlobalUnlock(data); |
432 } | 465 } |
433 | 466 |
434 void Clipboard::ReadAsciiText(ClipboardType type, std::string* result) const { | 467 void ClipboardWin::ReadAsciiText(ClipboardType type, |
| 468 std::string* result) const { |
435 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); | 469 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); |
436 if (!result) { | 470 if (!result) { |
437 NOTREACHED(); | 471 NOTREACHED(); |
438 return; | 472 return; |
439 } | 473 } |
440 | 474 |
441 result->clear(); | 475 result->clear(); |
442 | 476 |
443 // Acquire the clipboard. | 477 // Acquire the clipboard. |
444 ScopedClipboard clipboard; | 478 ScopedClipboard clipboard; |
445 if (!clipboard.Acquire(GetClipboardWindow())) | 479 if (!clipboard.Acquire(GetClipboardWindow())) |
446 return; | 480 return; |
447 | 481 |
448 HANDLE data = ::GetClipboardData(CF_TEXT); | 482 HANDLE data = ::GetClipboardData(CF_TEXT); |
449 if (!data) | 483 if (!data) |
450 return; | 484 return; |
451 | 485 |
452 result->assign(static_cast<const char*>(::GlobalLock(data))); | 486 result->assign(static_cast<const char*>(::GlobalLock(data))); |
453 ::GlobalUnlock(data); | 487 ::GlobalUnlock(data); |
454 } | 488 } |
455 | 489 |
456 void Clipboard::ReadHTML(ClipboardType type, | 490 void ClipboardWin::ReadHTML(ClipboardType type, |
457 base::string16* markup, | 491 base::string16* markup, |
458 std::string* src_url, | 492 std::string* src_url, |
459 uint32* fragment_start, | 493 uint32* fragment_start, |
460 uint32* fragment_end) const { | 494 uint32* fragment_end) const { |
461 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); | 495 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); |
462 | 496 |
463 markup->clear(); | 497 markup->clear(); |
464 // TODO(dcheng): Remove these checks, I don't think they should be optional. | 498 // TODO(dcheng): Remove these checks, I don't think they should be optional. |
465 DCHECK(src_url); | 499 DCHECK(src_url); |
466 if (src_url) | 500 if (src_url) |
467 src_url->clear(); | 501 src_url->clear(); |
468 *fragment_start = 0; | 502 *fragment_start = 0; |
469 *fragment_end = 0; | 503 *fragment_end = 0; |
470 | 504 |
471 // Acquire the clipboard. | 505 // Acquire the clipboard. |
472 ScopedClipboard clipboard; | 506 ScopedClipboard clipboard; |
473 if (!clipboard.Acquire(GetClipboardWindow())) | 507 if (!clipboard.Acquire(GetClipboardWindow())) |
474 return; | 508 return; |
475 | 509 |
476 HANDLE data = ::GetClipboardData(GetHtmlFormatType().ToUINT()); | 510 HANDLE data = ::GetClipboardData(GetHtmlFormatType().ToFormatEtc().cfFormat); |
477 if (!data) | 511 if (!data) |
478 return; | 512 return; |
479 | 513 |
480 std::string cf_html(static_cast<const char*>(::GlobalLock(data))); | 514 std::string cf_html(static_cast<const char*>(::GlobalLock(data))); |
481 ::GlobalUnlock(data); | 515 ::GlobalUnlock(data); |
482 | 516 |
483 size_t html_start = std::string::npos; | 517 size_t html_start = std::string::npos; |
484 size_t start_index = std::string::npos; | 518 size_t start_index = std::string::npos; |
485 size_t end_index = std::string::npos; | 519 size_t end_index = std::string::npos; |
486 ClipboardUtil::CFHtmlExtractMetadata(cf_html, src_url, &html_start, | 520 ClipboardUtil::CFHtmlExtractMetadata(cf_html, src_url, &html_start, |
(...skipping 11 matching lines...) Expand all Loading... |
498 | 532 |
499 std::vector<size_t> offsets; | 533 std::vector<size_t> offsets; |
500 offsets.push_back(start_index - html_start); | 534 offsets.push_back(start_index - html_start); |
501 offsets.push_back(end_index - html_start); | 535 offsets.push_back(end_index - html_start); |
502 markup->assign(base::UTF8ToUTF16AndAdjustOffsets(cf_html.data() + html_start, | 536 markup->assign(base::UTF8ToUTF16AndAdjustOffsets(cf_html.data() + html_start, |
503 &offsets)); | 537 &offsets)); |
504 *fragment_start = base::checked_cast<uint32>(offsets[0]); | 538 *fragment_start = base::checked_cast<uint32>(offsets[0]); |
505 *fragment_end = base::checked_cast<uint32>(offsets[1]); | 539 *fragment_end = base::checked_cast<uint32>(offsets[1]); |
506 } | 540 } |
507 | 541 |
508 void Clipboard::ReadRTF(ClipboardType type, std::string* result) const { | 542 void ClipboardWin::ReadRTF(ClipboardType type, std::string* result) const { |
509 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); | 543 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); |
510 | 544 |
511 ReadData(GetRtfFormatType(), result); | 545 ReadData(GetRtfFormatType(), result); |
512 } | 546 } |
513 | 547 |
514 SkBitmap Clipboard::ReadImage(ClipboardType type) const { | 548 SkBitmap ClipboardWin::ReadImage(ClipboardType type) const { |
515 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); | 549 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); |
516 | 550 |
517 // Acquire the clipboard. | 551 // Acquire the clipboard. |
518 ScopedClipboard clipboard; | 552 ScopedClipboard clipboard; |
519 if (!clipboard.Acquire(GetClipboardWindow())) | 553 if (!clipboard.Acquire(GetClipboardWindow())) |
520 return SkBitmap(); | 554 return SkBitmap(); |
521 | 555 |
522 // We use a DIB rather than a DDB here since ::GetObject() with the | 556 // We use a DIB rather than a DDB here since ::GetObject() with the |
523 // HBITMAP returned from ::GetClipboardData(CF_BITMAP) always reports a color | 557 // HBITMAP returned from ::GetClipboardData(CF_BITMAP) always reports a color |
524 // depth of 32bpp. | 558 // depth of 32bpp. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 bool has_invalid_alpha_channel = bitmap->bmiHeader.biBitCount < 32 || | 608 bool has_invalid_alpha_channel = bitmap->bmiHeader.biBitCount < 32 || |
575 BitmapHasInvalidPremultipliedColors(device_bitmap); | 609 BitmapHasInvalidPremultipliedColors(device_bitmap); |
576 if (has_invalid_alpha_channel) { | 610 if (has_invalid_alpha_channel) { |
577 MakeBitmapOpaque(device_bitmap); | 611 MakeBitmapOpaque(device_bitmap); |
578 } | 612 } |
579 } | 613 } |
580 | 614 |
581 return canvas.ExtractImageRep().sk_bitmap(); | 615 return canvas.ExtractImageRep().sk_bitmap(); |
582 } | 616 } |
583 | 617 |
584 void Clipboard::ReadCustomData(ClipboardType clipboard_type, | 618 void ClipboardWin::ReadCustomData(ClipboardType clipboard_type, |
585 const base::string16& type, | 619 const base::string16& type, |
586 base::string16* result) const { | 620 base::string16* result) const { |
587 DCHECK_EQ(clipboard_type, CLIPBOARD_TYPE_COPY_PASTE); | 621 DCHECK_EQ(clipboard_type, CLIPBOARD_TYPE_COPY_PASTE); |
588 | 622 |
589 // Acquire the clipboard. | 623 // Acquire the clipboard. |
590 ScopedClipboard clipboard; | 624 ScopedClipboard clipboard; |
591 if (!clipboard.Acquire(GetClipboardWindow())) | 625 if (!clipboard.Acquire(GetClipboardWindow())) |
592 return; | 626 return; |
593 | 627 |
594 HANDLE hdata = ::GetClipboardData(GetWebCustomDataFormatType().ToUINT()); | 628 HANDLE hdata = |
| 629 ::GetClipboardData(GetWebCustomDataFormatType().ToFormatEtc().cfFormat); |
595 if (!hdata) | 630 if (!hdata) |
596 return; | 631 return; |
597 | 632 |
598 ReadCustomDataForType(::GlobalLock(hdata), ::GlobalSize(hdata), type, result); | 633 ReadCustomDataForType(::GlobalLock(hdata), ::GlobalSize(hdata), type, result); |
599 ::GlobalUnlock(hdata); | 634 ::GlobalUnlock(hdata); |
600 } | 635 } |
601 | 636 |
602 void Clipboard::ReadBookmark(base::string16* title, std::string* url) const { | 637 void ClipboardWin::ReadBookmark(base::string16* title, std::string* url) const { |
603 if (title) | 638 if (title) |
604 title->clear(); | 639 title->clear(); |
605 | 640 |
606 if (url) | 641 if (url) |
607 url->clear(); | 642 url->clear(); |
608 | 643 |
609 // Acquire the clipboard. | 644 // Acquire the clipboard. |
610 ScopedClipboard clipboard; | 645 ScopedClipboard clipboard; |
611 if (!clipboard.Acquire(GetClipboardWindow())) | 646 if (!clipboard.Acquire(GetClipboardWindow())) |
612 return; | 647 return; |
613 | 648 |
614 HANDLE data = ::GetClipboardData(GetUrlWFormatType().ToUINT()); | 649 HANDLE data = ::GetClipboardData(GetUrlWFormatType().ToFormatEtc().cfFormat); |
615 if (!data) | 650 if (!data) |
616 return; | 651 return; |
617 | 652 |
618 base::string16 bookmark(static_cast<const base::char16*>(::GlobalLock(data))); | 653 base::string16 bookmark(static_cast<const base::char16*>(::GlobalLock(data))); |
619 ::GlobalUnlock(data); | 654 ::GlobalUnlock(data); |
620 | 655 |
621 ParseBookmarkClipboardFormat(bookmark, title, url); | 656 ParseBookmarkClipboardFormat(bookmark, title, url); |
622 } | 657 } |
623 | 658 |
624 void Clipboard::ReadData(const FormatType& format, std::string* result) const { | 659 void ClipboardWin::ReadData(const FormatType& format, |
| 660 std::string* result) const { |
625 if (!result) { | 661 if (!result) { |
626 NOTREACHED(); | 662 NOTREACHED(); |
627 return; | 663 return; |
628 } | 664 } |
629 | 665 |
630 ScopedClipboard clipboard; | 666 ScopedClipboard clipboard; |
631 if (!clipboard.Acquire(GetClipboardWindow())) | 667 if (!clipboard.Acquire(GetClipboardWindow())) |
632 return; | 668 return; |
633 | 669 |
634 HANDLE data = ::GetClipboardData(format.ToUINT()); | 670 HANDLE data = ::GetClipboardData(format.ToFormatEtc().cfFormat); |
635 if (!data) | 671 if (!data) |
636 return; | 672 return; |
637 | 673 |
638 result->assign(static_cast<const char*>(::GlobalLock(data)), | 674 result->assign(static_cast<const char*>(::GlobalLock(data)), |
639 ::GlobalSize(data)); | 675 ::GlobalSize(data)); |
640 ::GlobalUnlock(data); | 676 ::GlobalUnlock(data); |
641 } | 677 } |
642 | 678 |
643 // static | 679 void ClipboardWin::WriteObjects(ClipboardType type, const ObjectMap& objects) { |
644 void Clipboard::ParseBookmarkClipboardFormat(const base::string16& bookmark, | |
645 base::string16* title, | |
646 std::string* url) { | |
647 const base::string16 kDelim = base::ASCIIToUTF16("\r\n"); | |
648 | |
649 const size_t title_end = bookmark.find_first_of(kDelim); | |
650 if (title) | |
651 title->assign(bookmark.substr(0, title_end)); | |
652 | |
653 if (url) { | |
654 const size_t url_start = bookmark.find_first_not_of(kDelim, title_end); | |
655 if (url_start != base::string16::npos) { | |
656 *url = base::UTF16ToUTF8( | |
657 bookmark.substr(url_start, base::string16::npos)); | |
658 } | |
659 } | |
660 } | |
661 | |
662 void Clipboard::WriteObjects(ClipboardType type, const ObjectMap& objects) { | |
663 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); | 680 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); |
664 | 681 |
665 ScopedClipboard clipboard; | 682 ScopedClipboard clipboard; |
666 if (!clipboard.Acquire(GetClipboardWindow())) | 683 if (!clipboard.Acquire(GetClipboardWindow())) |
667 return; | 684 return; |
668 | 685 |
669 ::EmptyClipboard(); | 686 ::EmptyClipboard(); |
670 | 687 |
671 for (ObjectMap::const_iterator iter = objects.begin(); | 688 for (ObjectMap::const_iterator iter = objects.begin(); iter != objects.end(); |
672 iter != objects.end(); ++iter) { | 689 ++iter) { |
673 DispatchObject(static_cast<ObjectType>(iter->first), iter->second); | 690 DispatchObject(static_cast<ObjectType>(iter->first), iter->second); |
674 } | 691 } |
675 } | 692 } |
676 | 693 |
677 void Clipboard::WriteText(const char* text_data, size_t text_len) { | 694 void ClipboardWin::WriteText(const char* text_data, size_t text_len) { |
678 base::string16 text; | 695 base::string16 text; |
679 base::UTF8ToUTF16(text_data, text_len, &text); | 696 base::UTF8ToUTF16(text_data, text_len, &text); |
680 HGLOBAL glob = CreateGlobalData(text); | 697 HGLOBAL glob = CreateGlobalData(text); |
681 | 698 |
682 WriteToClipboard(CF_UNICODETEXT, glob); | 699 WriteToClipboard(CF_UNICODETEXT, glob); |
683 } | 700 } |
684 | 701 |
685 void Clipboard::WriteHTML(const char* markup_data, | 702 void ClipboardWin::WriteHTML(const char* markup_data, |
686 size_t markup_len, | 703 size_t markup_len, |
687 const char* url_data, | 704 const char* url_data, |
688 size_t url_len) { | 705 size_t url_len) { |
689 std::string markup(markup_data, markup_len); | 706 std::string markup(markup_data, markup_len); |
690 std::string url; | 707 std::string url; |
691 | 708 |
692 if (url_len > 0) | 709 if (url_len > 0) |
693 url.assign(url_data, url_len); | 710 url.assign(url_data, url_len); |
694 | 711 |
695 std::string html_fragment = ClipboardUtil::HtmlToCFHtml(markup, url); | 712 std::string html_fragment = ClipboardUtil::HtmlToCFHtml(markup, url); |
696 HGLOBAL glob = CreateGlobalData(html_fragment); | 713 HGLOBAL glob = CreateGlobalData(html_fragment); |
697 | 714 |
698 WriteToClipboard(Clipboard::GetHtmlFormatType().ToUINT(), glob); | 715 WriteToClipboard(Clipboard::GetHtmlFormatType().ToFormatEtc().cfFormat, glob); |
699 } | 716 } |
700 | 717 |
701 void Clipboard::WriteRTF(const char* rtf_data, size_t data_len) { | 718 void ClipboardWin::WriteRTF(const char* rtf_data, size_t data_len) { |
702 WriteData(GetRtfFormatType(), rtf_data, data_len); | 719 WriteData(GetRtfFormatType(), rtf_data, data_len); |
703 } | 720 } |
704 | 721 |
705 void Clipboard::WriteBookmark(const char* title_data, | 722 void ClipboardWin::WriteBookmark(const char* title_data, |
706 size_t title_len, | 723 size_t title_len, |
707 const char* url_data, | 724 const char* url_data, |
708 size_t url_len) { | 725 size_t url_len) { |
709 std::string bookmark(title_data, title_len); | 726 std::string bookmark(title_data, title_len); |
710 bookmark.append(1, L'\n'); | 727 bookmark.append(1, L'\n'); |
711 bookmark.append(url_data, url_len); | 728 bookmark.append(url_data, url_len); |
712 | 729 |
713 base::string16 wide_bookmark = base::UTF8ToWide(bookmark); | 730 base::string16 wide_bookmark = base::UTF8ToWide(bookmark); |
714 HGLOBAL glob = CreateGlobalData(wide_bookmark); | 731 HGLOBAL glob = CreateGlobalData(wide_bookmark); |
715 | 732 |
716 WriteToClipboard(GetUrlWFormatType().ToUINT(), glob); | 733 WriteToClipboard(GetUrlWFormatType().ToFormatEtc().cfFormat, glob); |
717 } | 734 } |
718 | 735 |
719 void Clipboard::WriteWebSmartPaste() { | 736 void ClipboardWin::WriteWebSmartPaste() { |
720 DCHECK(clipboard_owner_->hwnd() != NULL); | 737 DCHECK(clipboard_owner_->hwnd() != NULL); |
721 ::SetClipboardData(GetWebKitSmartPasteFormatType().ToUINT(), NULL); | 738 ::SetClipboardData(GetWebKitSmartPasteFormatType().ToFormatEtc().cfFormat, |
| 739 NULL); |
722 } | 740 } |
723 | 741 |
724 void Clipboard::WriteBitmap(const SkBitmap& bitmap) { | 742 void ClipboardWin::WriteBitmap(const SkBitmap& bitmap) { |
725 HDC dc = ::GetDC(NULL); | 743 HDC dc = ::GetDC(NULL); |
726 | 744 |
727 // This doesn't actually cost us a memcpy when the bitmap comes from the | 745 // This doesn't actually cost us a memcpy when the bitmap comes from the |
728 // renderer as we load it into the bitmap using setPixels which just sets a | 746 // renderer as we load it into the bitmap using setPixels which just sets a |
729 // pointer. Someone has to memcpy it into GDI, it might as well be us here. | 747 // pointer. Someone has to memcpy it into GDI, it might as well be us here. |
730 | 748 |
731 // TODO(darin): share data in gfx/bitmap_header.cc somehow | 749 // TODO(darin): share data in gfx/bitmap_header.cc somehow |
732 BITMAPINFO bm_info = {0}; | 750 BITMAPINFO bm_info = {0}; |
733 bm_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); | 751 bm_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); |
734 bm_info.bmiHeader.biWidth = bitmap.width(); | 752 bm_info.bmiHeader.biWidth = bitmap.width(); |
735 bm_info.bmiHeader.biHeight = -bitmap.height(); // sets vertical orientation | 753 bm_info.bmiHeader.biHeight = -bitmap.height(); // sets vertical orientation |
736 bm_info.bmiHeader.biPlanes = 1; | 754 bm_info.bmiHeader.biPlanes = 1; |
737 bm_info.bmiHeader.biBitCount = 32; | 755 bm_info.bmiHeader.biBitCount = 32; |
738 bm_info.bmiHeader.biCompression = BI_RGB; | 756 bm_info.bmiHeader.biCompression = BI_RGB; |
739 | 757 |
740 // ::CreateDIBSection allocates memory for us to copy our bitmap into. | 758 // ::CreateDIBSection allocates memory for us to copy our bitmap into. |
741 // Unfortunately, we can't write the created bitmap to the clipboard, | 759 // Unfortunately, we can't write the created bitmap to the clipboard, |
742 // (see http://msdn2.microsoft.com/en-us/library/ms532292.aspx) | 760 // (see http://msdn2.microsoft.com/en-us/library/ms532292.aspx) |
743 void *bits; | 761 void* bits; |
744 HBITMAP source_hbitmap = | 762 HBITMAP source_hbitmap = |
745 ::CreateDIBSection(dc, &bm_info, DIB_RGB_COLORS, &bits, NULL, 0); | 763 ::CreateDIBSection(dc, &bm_info, DIB_RGB_COLORS, &bits, NULL, 0); |
746 | 764 |
747 if (bits && source_hbitmap) { | 765 if (bits && source_hbitmap) { |
748 { | 766 { |
749 SkAutoLockPixels bitmap_lock(bitmap); | 767 SkAutoLockPixels bitmap_lock(bitmap); |
750 // Copy the bitmap out of shared memory and into GDI | 768 // Copy the bitmap out of shared memory and into GDI |
751 memcpy(bits, bitmap.getPixels(), bitmap.getSize()); | 769 memcpy(bits, bitmap.getPixels(), bitmap.getSize()); |
752 } | 770 } |
753 | 771 |
754 // Now we have an HBITMAP, we can write it to the clipboard | 772 // Now we have an HBITMAP, we can write it to the clipboard |
755 WriteBitmapFromHandle(source_hbitmap, | 773 WriteBitmapFromHandle(source_hbitmap, |
756 gfx::Size(bitmap.width(), bitmap.height())); | 774 gfx::Size(bitmap.width(), bitmap.height())); |
757 } | 775 } |
758 | 776 |
759 ::DeleteObject(source_hbitmap); | 777 ::DeleteObject(source_hbitmap); |
760 ::ReleaseDC(NULL, dc); | 778 ::ReleaseDC(NULL, dc); |
761 } | 779 } |
762 | 780 |
763 void Clipboard::WriteBitmapFromHandle(HBITMAP source_hbitmap, | 781 void ClipboardWin::WriteData(const FormatType& format, |
764 const gfx::Size& size) { | 782 const char* data_data, |
| 783 size_t data_len) { |
| 784 HGLOBAL hdata = ::GlobalAlloc(GMEM_MOVEABLE, data_len); |
| 785 if (!hdata) |
| 786 return; |
| 787 |
| 788 char* data = static_cast<char*>(::GlobalLock(hdata)); |
| 789 memcpy(data, data_data, data_len); |
| 790 ::GlobalUnlock(data); |
| 791 WriteToClipboard(format.ToFormatEtc().cfFormat, hdata); |
| 792 } |
| 793 |
| 794 void ClipboardWin::WriteBitmapFromHandle(HBITMAP source_hbitmap, |
| 795 const gfx::Size& size) { |
765 // We would like to just call ::SetClipboardData on the source_hbitmap, | 796 // We would like to just call ::SetClipboardData on the source_hbitmap, |
766 // but that bitmap might not be of a sort we can write to the clipboard. | 797 // but that bitmap might not be of a sort we can write to the clipboard. |
767 // For this reason, we create a new bitmap, copy the bits over, and then | 798 // For this reason, we create a new bitmap, copy the bits over, and then |
768 // write that to the clipboard. | 799 // write that to the clipboard. |
769 | 800 |
770 HDC dc = ::GetDC(NULL); | 801 HDC dc = ::GetDC(NULL); |
771 HDC compatible_dc = ::CreateCompatibleDC(NULL); | 802 HDC compatible_dc = ::CreateCompatibleDC(NULL); |
772 HDC source_dc = ::CreateCompatibleDC(NULL); | 803 HDC source_dc = ::CreateCompatibleDC(NULL); |
773 | 804 |
774 // This is the HBITMAP we will eventually write to the clipboard | 805 // This is the HBITMAP we will eventually write to the clipboard |
775 HBITMAP hbitmap = ::CreateCompatibleBitmap(dc, size.width(), size.height()); | 806 HBITMAP hbitmap = ::CreateCompatibleBitmap(dc, size.width(), size.height()); |
776 if (!hbitmap) { | 807 if (!hbitmap) { |
777 // Failed to create the bitmap | 808 // Failed to create the bitmap |
778 ::DeleteDC(compatible_dc); | 809 ::DeleteDC(compatible_dc); |
779 ::DeleteDC(source_dc); | 810 ::DeleteDC(source_dc); |
780 ::ReleaseDC(NULL, dc); | 811 ::ReleaseDC(NULL, dc); |
781 return; | 812 return; |
782 } | 813 } |
783 | 814 |
784 HBITMAP old_hbitmap = (HBITMAP)SelectObject(compatible_dc, hbitmap); | 815 HBITMAP old_hbitmap = (HBITMAP)SelectObject(compatible_dc, hbitmap); |
785 HBITMAP old_source = (HBITMAP)SelectObject(source_dc, source_hbitmap); | 816 HBITMAP old_source = (HBITMAP)SelectObject(source_dc, source_hbitmap); |
786 | 817 |
787 // Now we need to blend it into an HBITMAP we can place on the clipboard | 818 // Now we need to blend it into an HBITMAP we can place on the clipboard |
788 BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA}; | 819 BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA}; |
789 ::GdiAlphaBlend(compatible_dc, 0, 0, size.width(), size.height(), | 820 ::GdiAlphaBlend(compatible_dc, |
790 source_dc, 0, 0, size.width(), size.height(), bf); | 821 0, |
| 822 0, |
| 823 size.width(), |
| 824 size.height(), |
| 825 source_dc, |
| 826 0, |
| 827 0, |
| 828 size.width(), |
| 829 size.height(), |
| 830 bf); |
791 | 831 |
792 // Clean up all the handles we just opened | 832 // Clean up all the handles we just opened |
793 ::SelectObject(compatible_dc, old_hbitmap); | 833 ::SelectObject(compatible_dc, old_hbitmap); |
794 ::SelectObject(source_dc, old_source); | 834 ::SelectObject(source_dc, old_source); |
795 ::DeleteObject(old_hbitmap); | 835 ::DeleteObject(old_hbitmap); |
796 ::DeleteObject(old_source); | 836 ::DeleteObject(old_source); |
797 ::DeleteDC(compatible_dc); | 837 ::DeleteDC(compatible_dc); |
798 ::DeleteDC(source_dc); | 838 ::DeleteDC(source_dc); |
799 ::ReleaseDC(NULL, dc); | 839 ::ReleaseDC(NULL, dc); |
800 | 840 |
801 WriteToClipboard(CF_BITMAP, hbitmap); | 841 WriteToClipboard(CF_BITMAP, hbitmap); |
802 } | 842 } |
803 | 843 |
804 void Clipboard::WriteData(const FormatType& format, | 844 void ClipboardWin::WriteToClipboard(unsigned int format, HANDLE handle) { |
805 const char* data_data, | |
806 size_t data_len) { | |
807 HGLOBAL hdata = ::GlobalAlloc(GMEM_MOVEABLE, data_len); | |
808 if (!hdata) | |
809 return; | |
810 | |
811 char* data = static_cast<char*>(::GlobalLock(hdata)); | |
812 memcpy(data, data_data, data_len); | |
813 ::GlobalUnlock(data); | |
814 WriteToClipboard(format.ToUINT(), hdata); | |
815 } | |
816 | |
817 void Clipboard::WriteToClipboard(unsigned int format, HANDLE handle) { | |
818 DCHECK(clipboard_owner_->hwnd() != NULL); | 845 DCHECK(clipboard_owner_->hwnd() != NULL); |
819 if (handle && !::SetClipboardData(format, handle)) { | 846 if (handle && !::SetClipboardData(format, handle)) { |
820 DCHECK(ERROR_CLIPBOARD_NOT_OPEN != GetLastError()); | 847 DCHECK(ERROR_CLIPBOARD_NOT_OPEN != GetLastError()); |
821 FreeData(format, handle); | 848 FreeData(format, handle); |
822 } | 849 } |
823 } | 850 } |
824 | 851 |
825 // static | 852 HWND ClipboardWin::GetClipboardWindow() const { |
826 void Clipboard::FreeData(unsigned int format, HANDLE data) { | |
827 if (format == CF_BITMAP) | |
828 ::DeleteObject(static_cast<HBITMAP>(data)); | |
829 else | |
830 ::GlobalFree(data); | |
831 } | |
832 | |
833 HWND Clipboard::GetClipboardWindow() const { | |
834 if (!clipboard_owner_) | 853 if (!clipboard_owner_) |
835 return NULL; | 854 return NULL; |
836 | 855 |
837 if (clipboard_owner_->hwnd() == NULL) | 856 if (clipboard_owner_->hwnd() == NULL) |
838 clipboard_owner_->Create(base::Bind(&ClipboardOwnerWndProc)); | 857 clipboard_owner_->Create(base::Bind(&ClipboardOwnerWndProc)); |
839 | 858 |
840 return clipboard_owner_->hwnd(); | 859 return clipboard_owner_->hwnd(); |
841 } | 860 } |
842 | 861 |
843 } // namespace ui | 862 } // namespace ui |
OLD | NEW |