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

Unified Diff: ui/base/clipboard/clipboard_win.cc

Issue 851853002: It is time. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Trying to reup because the last upload failed. Created 5 years, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/base/clipboard/clipboard_win.h ('k') | ui/base/clipboard/custom_data_helper.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/base/clipboard/clipboard_win.cc
diff --git a/ui/base/clipboard/clipboard_win.cc b/ui/base/clipboard/clipboard_win.cc
deleted file mode 100644
index f37f0772cadf2912f9c26ea0520d041e99e9cbb7..0000000000000000000000000000000000000000
--- a/ui/base/clipboard/clipboard_win.cc
+++ /dev/null
@@ -1,862 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Many of these functions are based on those found in
-// webkit/port/platform/PasteboardWin.cpp
-
-#include "ui/base/clipboard/clipboard_win.h"
-
-#include <shellapi.h>
-#include <shlobj.h>
-
-#include "base/basictypes.h"
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "base/logging.h"
-#include "base/memory/shared_memory.h"
-#include "base/message_loop/message_loop.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_offset_string_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/win/message_window.h"
-#include "base/win/scoped_gdi_object.h"
-#include "base/win/scoped_hdc.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/base/clipboard/clipboard_util_win.h"
-#include "ui/base/clipboard/custom_data_helper.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/size.h"
-
-namespace ui {
-
-namespace {
-
-// A scoper to manage acquiring and automatically releasing the clipboard.
-class ScopedClipboard {
- public:
- ScopedClipboard() : opened_(false) { }
-
- ~ScopedClipboard() {
- if (opened_)
- Release();
- }
-
- bool Acquire(HWND owner) {
- const int kMaxAttemptsToOpenClipboard = 5;
-
- if (opened_) {
- NOTREACHED();
- return false;
- }
-
- // Attempt to open the clipboard, which will acquire the Windows clipboard
- // lock. This may fail if another process currently holds this lock.
- // We're willing to try a few times in the hopes of acquiring it.
- //
- // This turns out to be an issue when using remote desktop because the
- // rdpclip.exe process likes to read what we've written to the clipboard and
- // send it to the RDP client. If we open and close the clipboard in quick
- // succession, we might be trying to open it while rdpclip.exe has it open,
- // See Bug 815425.
- //
- // In fact, we believe we'll only spin this loop over remote desktop. In
- // normal situations, the user is initiating clipboard operations and there
- // shouldn't be contention.
-
- for (int attempts = 0; attempts < kMaxAttemptsToOpenClipboard; ++attempts) {
- // If we didn't manage to open the clipboard, sleep a bit and be hopeful.
- if (attempts != 0)
- ::Sleep(5);
-
- if (::OpenClipboard(owner)) {
- opened_ = true;
- return true;
- }
- }
-
- // We failed to acquire the clipboard.
- return false;
- }
-
- void Release() {
- if (opened_) {
- ::CloseClipboard();
- opened_ = false;
- } else {
- NOTREACHED();
- }
- }
-
- private:
- bool opened_;
-};
-
-bool ClipboardOwnerWndProc(UINT message,
- WPARAM wparam,
- LPARAM lparam,
- LRESULT* result) {
- switch (message) {
- case WM_RENDERFORMAT:
- // This message comes when SetClipboardData was sent a null data handle
- // and now it's come time to put the data on the clipboard.
- // We always set data, so there isn't a need to actually do anything here.
- break;
- case WM_RENDERALLFORMATS:
- // This message comes when SetClipboardData was sent a null data handle
- // and now this application is about to quit, so it must put data on
- // the clipboard before it exits.
- // We always set data, so there isn't a need to actually do anything here.
- break;
- case WM_DRAWCLIPBOARD:
- break;
- case WM_DESTROY:
- break;
- case WM_CHANGECBCHAIN:
- break;
- default:
- return false;
- }
-
- *result = 0;
- return true;
-}
-
-template <typename charT>
-HGLOBAL CreateGlobalData(const std::basic_string<charT>& str) {
- HGLOBAL data =
- ::GlobalAlloc(GMEM_MOVEABLE, ((str.size() + 1) * sizeof(charT)));
- if (data) {
- charT* raw_data = static_cast<charT*>(::GlobalLock(data));
- memcpy(raw_data, str.data(), str.size() * sizeof(charT));
- raw_data[str.size()] = '\0';
- ::GlobalUnlock(data);
- }
- return data;
-};
-
-bool BitmapHasInvalidPremultipliedColors(const SkBitmap& bitmap) {
- for (int x = 0; x < bitmap.width(); ++x) {
- for (int y = 0; y < bitmap.height(); ++y) {
- uint32_t pixel = *bitmap.getAddr32(x, y);
- if (SkColorGetR(pixel) > SkColorGetA(pixel) ||
- SkColorGetG(pixel) > SkColorGetA(pixel) ||
- SkColorGetB(pixel) > SkColorGetA(pixel))
- return true;
- }
- }
- return false;
-}
-
-void MakeBitmapOpaque(const SkBitmap& bitmap) {
- for (int x = 0; x < bitmap.width(); ++x) {
- for (int y = 0; y < bitmap.height(); ++y) {
- *bitmap.getAddr32(x, y) = SkColorSetA(*bitmap.getAddr32(x, y), 0xFF);
- }
- }
-}
-
-void ParseBookmarkClipboardFormat(const base::string16& bookmark,
- base::string16* title,
- std::string* url) {
- const base::string16 kDelim = base::ASCIIToUTF16("\r\n");
-
- const size_t title_end = bookmark.find_first_of(kDelim);
- if (title)
- title->assign(bookmark.substr(0, title_end));
-
- if (url) {
- const size_t url_start = bookmark.find_first_not_of(kDelim, title_end);
- if (url_start != base::string16::npos) {
- *url =
- base::UTF16ToUTF8(bookmark.substr(url_start, base::string16::npos));
- }
- }
-}
-
-void FreeData(unsigned int format, HANDLE data) {
- if (format == CF_BITMAP)
- ::DeleteObject(static_cast<HBITMAP>(data));
- else
- ::GlobalFree(data);
-}
-
-} // namespace
-
-// Clipboard::FormatType implementation.
-Clipboard::FormatType::FormatType() : data_() {}
-
-Clipboard::FormatType::FormatType(UINT native_format) : data_() {
- // There's no good way to actually initialize this in the constructor in
- // C++03.
- data_.cfFormat = static_cast<CLIPFORMAT>(native_format);
- data_.dwAspect = DVASPECT_CONTENT;
- data_.lindex = -1;
- data_.tymed = TYMED_HGLOBAL;
-}
-
-Clipboard::FormatType::FormatType(UINT native_format, LONG index) : data_() {
- // There's no good way to actually initialize this in the constructor in
- // C++03.
- data_.cfFormat = static_cast<CLIPFORMAT>(native_format);
- data_.dwAspect = DVASPECT_CONTENT;
- data_.lindex = index;
- data_.tymed = TYMED_HGLOBAL;
-}
-
-Clipboard::FormatType::~FormatType() {
-}
-
-std::string Clipboard::FormatType::Serialize() const {
- return base::IntToString(data_.cfFormat);
-}
-
-// static
-Clipboard::FormatType Clipboard::FormatType::Deserialize(
- const std::string& serialization) {
- int clipboard_format = -1;
- if (!base::StringToInt(serialization, &clipboard_format)) {
- NOTREACHED();
- return FormatType();
- }
- return FormatType(clipboard_format);
-}
-
-bool Clipboard::FormatType::operator<(const FormatType& other) const {
- return data_.cfFormat < other.data_.cfFormat;
-}
-
-bool Clipboard::FormatType::Equals(const FormatType& other) const {
- return data_.cfFormat == other.data_.cfFormat;
-}
-
-// Various predefined FormatTypes.
-// static
-Clipboard::FormatType Clipboard::GetFormatType(
- const std::string& format_string) {
- return FormatType(
- ::RegisterClipboardFormat(base::ASCIIToWide(format_string).c_str()));
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetUrlFormatType() {
- CR_DEFINE_STATIC_LOCAL(
- FormatType, type, (::RegisterClipboardFormat(CFSTR_INETURLA)));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetUrlWFormatType() {
- CR_DEFINE_STATIC_LOCAL(
- FormatType, type, (::RegisterClipboardFormat(CFSTR_INETURLW)));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetMozUrlFormatType() {
- CR_DEFINE_STATIC_LOCAL(
- FormatType, type, (::RegisterClipboardFormat(L"text/x-moz-url")));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetPlainTextFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_TEXT));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetPlainTextWFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_UNICODETEXT));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetFilenameFormatType() {
- CR_DEFINE_STATIC_LOCAL(
- FormatType, type, (::RegisterClipboardFormat(CFSTR_FILENAMEA)));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetFilenameWFormatType() {
- CR_DEFINE_STATIC_LOCAL(
- FormatType, type, (::RegisterClipboardFormat(CFSTR_FILENAMEW)));
- return type;
-}
-
-// MS HTML Format
-// static
-const Clipboard::FormatType& Clipboard::GetHtmlFormatType() {
- CR_DEFINE_STATIC_LOCAL(
- FormatType, type, (::RegisterClipboardFormat(L"HTML Format")));
- return type;
-}
-
-// MS RTF Format
-// static
-const Clipboard::FormatType& Clipboard::GetRtfFormatType() {
- CR_DEFINE_STATIC_LOCAL(
- FormatType, type, (::RegisterClipboardFormat(L"Rich Text Format")));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetBitmapFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_BITMAP));
- return type;
-}
-
-// Firefox text/html
-// static
-const Clipboard::FormatType& Clipboard::GetTextHtmlFormatType() {
- CR_DEFINE_STATIC_LOCAL(
- FormatType, type, (::RegisterClipboardFormat(L"text/html")));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetCFHDropFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_HDROP));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetFileDescriptorFormatType() {
- CR_DEFINE_STATIC_LOCAL(
- FormatType, type, (::RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR)));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetFileContentZeroFormatType() {
- CR_DEFINE_STATIC_LOCAL(
- FormatType, type, (::RegisterClipboardFormat(CFSTR_FILECONTENTS), 0));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetIDListFormatType() {
- CR_DEFINE_STATIC_LOCAL(
- FormatType, type, (::RegisterClipboardFormat(CFSTR_SHELLIDLIST)));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetWebKitSmartPasteFormatType() {
- CR_DEFINE_STATIC_LOCAL(
- FormatType,
- type,
- (::RegisterClipboardFormat(L"WebKit Smart Paste Format")));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetWebCustomDataFormatType() {
- // TODO(dcheng): This name is temporary. See http://crbug.com/106449.
- CR_DEFINE_STATIC_LOCAL(
- FormatType,
- type,
- (::RegisterClipboardFormat(L"Chromium Web Custom MIME Data Format")));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() {
- CR_DEFINE_STATIC_LOCAL(
- FormatType,
- type,
- (::RegisterClipboardFormat(L"Chromium Pepper MIME Data Format")));
- return type;
-}
-
-// Clipboard factory method.
-// static
-Clipboard* Clipboard::Create() {
- return new ClipboardWin;
-}
-
-// ClipboardWin implementation.
-ClipboardWin::ClipboardWin() {
- if (base::MessageLoopForUI::IsCurrent())
- clipboard_owner_.reset(new base::win::MessageWindow());
-}
-
-ClipboardWin::~ClipboardWin() {
-}
-
-uint64 ClipboardWin::GetSequenceNumber(ClipboardType type) {
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
- return ::GetClipboardSequenceNumber();
-}
-
-bool ClipboardWin::IsFormatAvailable(const Clipboard::FormatType& format,
- ClipboardType type) const {
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
- return ::IsClipboardFormatAvailable(format.ToFormatEtc().cfFormat) != FALSE;
-}
-
-void ClipboardWin::Clear(ClipboardType type) {
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
- ScopedClipboard clipboard;
- if (!clipboard.Acquire(GetClipboardWindow()))
- return;
-
- ::EmptyClipboard();
-}
-
-void ClipboardWin::ReadAvailableTypes(ClipboardType type,
- std::vector<base::string16>* types,
- bool* contains_filenames) const {
- if (!types || !contains_filenames) {
- NOTREACHED();
- return;
- }
-
- types->clear();
- if (::IsClipboardFormatAvailable(
- GetPlainTextFormatType().ToFormatEtc().cfFormat))
- types->push_back(base::UTF8ToUTF16(kMimeTypeText));
- if (::IsClipboardFormatAvailable(GetHtmlFormatType().ToFormatEtc().cfFormat))
- types->push_back(base::UTF8ToUTF16(kMimeTypeHTML));
- if (::IsClipboardFormatAvailable(GetRtfFormatType().ToFormatEtc().cfFormat))
- types->push_back(base::UTF8ToUTF16(kMimeTypeRTF));
- if (::IsClipboardFormatAvailable(CF_DIB))
- types->push_back(base::UTF8ToUTF16(kMimeTypePNG));
- *contains_filenames = false;
-
- // Acquire the clipboard.
- ScopedClipboard clipboard;
- if (!clipboard.Acquire(GetClipboardWindow()))
- return;
-
- HANDLE hdata =
- ::GetClipboardData(GetWebCustomDataFormatType().ToFormatEtc().cfFormat);
- if (!hdata)
- return;
-
- ReadCustomDataTypes(::GlobalLock(hdata), ::GlobalSize(hdata), types);
- ::GlobalUnlock(hdata);
-}
-
-void ClipboardWin::ReadText(ClipboardType type, base::string16* result) const {
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
- if (!result) {
- NOTREACHED();
- return;
- }
-
- result->clear();
-
- // Acquire the clipboard.
- ScopedClipboard clipboard;
- if (!clipboard.Acquire(GetClipboardWindow()))
- return;
-
- HANDLE data = ::GetClipboardData(CF_UNICODETEXT);
- if (!data)
- return;
-
- result->assign(static_cast<const base::char16*>(::GlobalLock(data)));
- ::GlobalUnlock(data);
-}
-
-void ClipboardWin::ReadAsciiText(ClipboardType type,
- std::string* result) const {
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
- if (!result) {
- NOTREACHED();
- return;
- }
-
- result->clear();
-
- // Acquire the clipboard.
- ScopedClipboard clipboard;
- if (!clipboard.Acquire(GetClipboardWindow()))
- return;
-
- HANDLE data = ::GetClipboardData(CF_TEXT);
- if (!data)
- return;
-
- result->assign(static_cast<const char*>(::GlobalLock(data)));
- ::GlobalUnlock(data);
-}
-
-void ClipboardWin::ReadHTML(ClipboardType type,
- base::string16* markup,
- std::string* src_url,
- uint32* fragment_start,
- uint32* fragment_end) const {
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
-
- markup->clear();
- // TODO(dcheng): Remove these checks, I don't think they should be optional.
- DCHECK(src_url);
- if (src_url)
- src_url->clear();
- *fragment_start = 0;
- *fragment_end = 0;
-
- // Acquire the clipboard.
- ScopedClipboard clipboard;
- if (!clipboard.Acquire(GetClipboardWindow()))
- return;
-
- HANDLE data = ::GetClipboardData(GetHtmlFormatType().ToFormatEtc().cfFormat);
- if (!data)
- return;
-
- std::string cf_html(static_cast<const char*>(::GlobalLock(data)));
- ::GlobalUnlock(data);
-
- size_t html_start = std::string::npos;
- size_t start_index = std::string::npos;
- size_t end_index = std::string::npos;
- ClipboardUtil::CFHtmlExtractMetadata(cf_html, src_url, &html_start,
- &start_index, &end_index);
-
- // This might happen if the contents of the clipboard changed and CF_HTML is
- // no longer available.
- if (start_index == std::string::npos ||
- end_index == std::string::npos ||
- html_start == std::string::npos)
- return;
-
- if (start_index < html_start || end_index < start_index)
- return;
-
- std::vector<size_t> offsets;
- offsets.push_back(start_index - html_start);
- offsets.push_back(end_index - html_start);
- markup->assign(base::UTF8ToUTF16AndAdjustOffsets(cf_html.data() + html_start,
- &offsets));
- *fragment_start = base::checked_cast<uint32>(offsets[0]);
- *fragment_end = base::checked_cast<uint32>(offsets[1]);
-}
-
-void ClipboardWin::ReadRTF(ClipboardType type, std::string* result) const {
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
-
- ReadData(GetRtfFormatType(), result);
-}
-
-SkBitmap ClipboardWin::ReadImage(ClipboardType type) const {
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
-
- // Acquire the clipboard.
- ScopedClipboard clipboard;
- if (!clipboard.Acquire(GetClipboardWindow()))
- return SkBitmap();
-
- // We use a DIB rather than a DDB here since ::GetObject() with the
- // HBITMAP returned from ::GetClipboardData(CF_BITMAP) always reports a color
- // depth of 32bpp.
- BITMAPINFO* bitmap = static_cast<BITMAPINFO*>(::GetClipboardData(CF_DIB));
- if (!bitmap)
- return SkBitmap();
- int color_table_length = 0;
- switch (bitmap->bmiHeader.biBitCount) {
- case 1:
- case 4:
- case 8:
- color_table_length = bitmap->bmiHeader.biClrUsed
- ? bitmap->bmiHeader.biClrUsed
- : 1 << bitmap->bmiHeader.biBitCount;
- break;
- case 16:
- case 32:
- if (bitmap->bmiHeader.biCompression == BI_BITFIELDS)
- color_table_length = 3;
- break;
- case 24:
- break;
- default:
- NOTREACHED();
- }
- const void* bitmap_bits = reinterpret_cast<const char*>(bitmap)
- + bitmap->bmiHeader.biSize + color_table_length * sizeof(RGBQUAD);
-
- gfx::Canvas canvas(gfx::Size(bitmap->bmiHeader.biWidth,
- bitmap->bmiHeader.biHeight),
- 1.0f,
- false);
- {
- skia::ScopedPlatformPaint scoped_platform_paint(canvas.sk_canvas());
- HDC dc = scoped_platform_paint.GetPlatformSurface();
- ::SetDIBitsToDevice(dc, 0, 0, bitmap->bmiHeader.biWidth,
- bitmap->bmiHeader.biHeight, 0, 0, 0,
- bitmap->bmiHeader.biHeight, bitmap_bits, bitmap,
- DIB_RGB_COLORS);
- }
- // Windows doesn't really handle alpha channels well in many situations. When
- // the source image is < 32 bpp, we force the bitmap to be opaque. When the
- // source image is 32 bpp, the alpha channel might still contain garbage data.
- // Since Windows uses premultiplied alpha, we scan for instances where
- // (R, G, B) > A. If there are any invalid premultiplied colors in the image,
- // we assume the alpha channel contains garbage and force the bitmap to be
- // opaque as well. Note that this heuristic will fail on a transparent bitmap
- // containing only black pixels...
- const SkBitmap& device_bitmap =
- canvas.sk_canvas()->getDevice()->accessBitmap(true);
- {
- SkAutoLockPixels lock(device_bitmap);
- bool has_invalid_alpha_channel = bitmap->bmiHeader.biBitCount < 32 ||
- BitmapHasInvalidPremultipliedColors(device_bitmap);
- if (has_invalid_alpha_channel) {
- MakeBitmapOpaque(device_bitmap);
- }
- }
-
- return canvas.ExtractImageRep().sk_bitmap();
-}
-
-void ClipboardWin::ReadCustomData(ClipboardType clipboard_type,
- const base::string16& type,
- base::string16* result) const {
- DCHECK_EQ(clipboard_type, CLIPBOARD_TYPE_COPY_PASTE);
-
- // Acquire the clipboard.
- ScopedClipboard clipboard;
- if (!clipboard.Acquire(GetClipboardWindow()))
- return;
-
- HANDLE hdata =
- ::GetClipboardData(GetWebCustomDataFormatType().ToFormatEtc().cfFormat);
- if (!hdata)
- return;
-
- ReadCustomDataForType(::GlobalLock(hdata), ::GlobalSize(hdata), type, result);
- ::GlobalUnlock(hdata);
-}
-
-void ClipboardWin::ReadBookmark(base::string16* title, std::string* url) const {
- if (title)
- title->clear();
-
- if (url)
- url->clear();
-
- // Acquire the clipboard.
- ScopedClipboard clipboard;
- if (!clipboard.Acquire(GetClipboardWindow()))
- return;
-
- HANDLE data = ::GetClipboardData(GetUrlWFormatType().ToFormatEtc().cfFormat);
- if (!data)
- return;
-
- base::string16 bookmark(static_cast<const base::char16*>(::GlobalLock(data)));
- ::GlobalUnlock(data);
-
- ParseBookmarkClipboardFormat(bookmark, title, url);
-}
-
-void ClipboardWin::ReadData(const FormatType& format,
- std::string* result) const {
- if (!result) {
- NOTREACHED();
- return;
- }
-
- ScopedClipboard clipboard;
- if (!clipboard.Acquire(GetClipboardWindow()))
- return;
-
- HANDLE data = ::GetClipboardData(format.ToFormatEtc().cfFormat);
- if (!data)
- return;
-
- result->assign(static_cast<const char*>(::GlobalLock(data)),
- ::GlobalSize(data));
- ::GlobalUnlock(data);
-}
-
-void ClipboardWin::WriteObjects(ClipboardType type, const ObjectMap& objects) {
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
-
- ScopedClipboard clipboard;
- if (!clipboard.Acquire(GetClipboardWindow()))
- return;
-
- ::EmptyClipboard();
-
- for (ObjectMap::const_iterator iter = objects.begin(); iter != objects.end();
- ++iter) {
- DispatchObject(static_cast<ObjectType>(iter->first), iter->second);
- }
-}
-
-void ClipboardWin::WriteText(const char* text_data, size_t text_len) {
- base::string16 text;
- base::UTF8ToUTF16(text_data, text_len, &text);
- HGLOBAL glob = CreateGlobalData(text);
-
- WriteToClipboard(CF_UNICODETEXT, glob);
-}
-
-void ClipboardWin::WriteHTML(const char* markup_data,
- size_t markup_len,
- const char* url_data,
- size_t url_len) {
- std::string markup(markup_data, markup_len);
- std::string url;
-
- if (url_len > 0)
- url.assign(url_data, url_len);
-
- std::string html_fragment = ClipboardUtil::HtmlToCFHtml(markup, url);
- HGLOBAL glob = CreateGlobalData(html_fragment);
-
- WriteToClipboard(Clipboard::GetHtmlFormatType().ToFormatEtc().cfFormat, glob);
-}
-
-void ClipboardWin::WriteRTF(const char* rtf_data, size_t data_len) {
- WriteData(GetRtfFormatType(), rtf_data, data_len);
-}
-
-void ClipboardWin::WriteBookmark(const char* title_data,
- size_t title_len,
- const char* url_data,
- size_t url_len) {
- std::string bookmark(title_data, title_len);
- bookmark.append(1, L'\n');
- bookmark.append(url_data, url_len);
-
- base::string16 wide_bookmark = base::UTF8ToWide(bookmark);
- HGLOBAL glob = CreateGlobalData(wide_bookmark);
-
- WriteToClipboard(GetUrlWFormatType().ToFormatEtc().cfFormat, glob);
-}
-
-void ClipboardWin::WriteWebSmartPaste() {
- DCHECK(clipboard_owner_->hwnd() != NULL);
- ::SetClipboardData(GetWebKitSmartPasteFormatType().ToFormatEtc().cfFormat,
- NULL);
-}
-
-void ClipboardWin::WriteBitmap(const SkBitmap& bitmap) {
- HDC dc = ::GetDC(NULL);
-
- // This doesn't actually cost us a memcpy when the bitmap comes from the
- // renderer as we load it into the bitmap using setPixels which just sets a
- // pointer. Someone has to memcpy it into GDI, it might as well be us here.
-
- // TODO(darin): share data in gfx/bitmap_header.cc somehow
- BITMAPINFO bm_info = {0};
- bm_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bm_info.bmiHeader.biWidth = bitmap.width();
- bm_info.bmiHeader.biHeight = -bitmap.height(); // sets vertical orientation
- bm_info.bmiHeader.biPlanes = 1;
- bm_info.bmiHeader.biBitCount = 32;
- bm_info.bmiHeader.biCompression = BI_RGB;
-
- // ::CreateDIBSection allocates memory for us to copy our bitmap into.
- // Unfortunately, we can't write the created bitmap to the clipboard,
- // (see http://msdn2.microsoft.com/en-us/library/ms532292.aspx)
- void* bits;
- HBITMAP source_hbitmap =
- ::CreateDIBSection(dc, &bm_info, DIB_RGB_COLORS, &bits, NULL, 0);
-
- if (bits && source_hbitmap) {
- {
- SkAutoLockPixels bitmap_lock(bitmap);
- // Copy the bitmap out of shared memory and into GDI
- memcpy(bits, bitmap.getPixels(), bitmap.getSize());
- }
-
- // Now we have an HBITMAP, we can write it to the clipboard
- WriteBitmapFromHandle(source_hbitmap,
- gfx::Size(bitmap.width(), bitmap.height()));
- }
-
- ::DeleteObject(source_hbitmap);
- ::ReleaseDC(NULL, dc);
-}
-
-void ClipboardWin::WriteData(const FormatType& format,
- const char* data_data,
- size_t data_len) {
- HGLOBAL hdata = ::GlobalAlloc(GMEM_MOVEABLE, data_len);
- if (!hdata)
- return;
-
- char* data = static_cast<char*>(::GlobalLock(hdata));
- memcpy(data, data_data, data_len);
- ::GlobalUnlock(data);
- WriteToClipboard(format.ToFormatEtc().cfFormat, hdata);
-}
-
-void ClipboardWin::WriteBitmapFromHandle(HBITMAP source_hbitmap,
- const gfx::Size& size) {
- // We would like to just call ::SetClipboardData on the source_hbitmap,
- // but that bitmap might not be of a sort we can write to the clipboard.
- // For this reason, we create a new bitmap, copy the bits over, and then
- // write that to the clipboard.
-
- HDC dc = ::GetDC(NULL);
- HDC compatible_dc = ::CreateCompatibleDC(NULL);
- HDC source_dc = ::CreateCompatibleDC(NULL);
-
- // This is the HBITMAP we will eventually write to the clipboard
- HBITMAP hbitmap = ::CreateCompatibleBitmap(dc, size.width(), size.height());
- if (!hbitmap) {
- // Failed to create the bitmap
- ::DeleteDC(compatible_dc);
- ::DeleteDC(source_dc);
- ::ReleaseDC(NULL, dc);
- return;
- }
-
- HBITMAP old_hbitmap = (HBITMAP)SelectObject(compatible_dc, hbitmap);
- HBITMAP old_source = (HBITMAP)SelectObject(source_dc, source_hbitmap);
-
- // Now we need to blend it into an HBITMAP we can place on the clipboard
- BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
- ::GdiAlphaBlend(compatible_dc,
- 0,
- 0,
- size.width(),
- size.height(),
- source_dc,
- 0,
- 0,
- size.width(),
- size.height(),
- bf);
-
- // Clean up all the handles we just opened
- ::SelectObject(compatible_dc, old_hbitmap);
- ::SelectObject(source_dc, old_source);
- ::DeleteObject(old_hbitmap);
- ::DeleteObject(old_source);
- ::DeleteDC(compatible_dc);
- ::DeleteDC(source_dc);
- ::ReleaseDC(NULL, dc);
-
- WriteToClipboard(CF_BITMAP, hbitmap);
-}
-
-void ClipboardWin::WriteToClipboard(unsigned int format, HANDLE handle) {
- DCHECK(clipboard_owner_->hwnd() != NULL);
- if (handle && !::SetClipboardData(format, handle)) {
- DCHECK(ERROR_CLIPBOARD_NOT_OPEN != GetLastError());
- FreeData(format, handle);
- }
-}
-
-HWND ClipboardWin::GetClipboardWindow() const {
- if (!clipboard_owner_)
- return NULL;
-
- if (clipboard_owner_->hwnd() == NULL)
- clipboard_owner_->Create(base::Bind(&ClipboardOwnerWndProc));
-
- return clipboard_owner_->hwnd();
-}
-
-} // namespace ui
« no previous file with comments | « ui/base/clipboard/clipboard_win.h ('k') | ui/base/clipboard/custom_data_helper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698