| 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 |