| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 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 <shlobj.h> | 8 #include <shlobj.h> |
| 9 #include <shellapi.h> | 9 #include <shellapi.h> |
| 10 | 10 |
| 11 #include "base/clipboard.h" | 11 #include "base/clipboard.h" |
| 12 | 12 |
| 13 #include "base/clipboard_util.h" | 13 #include "base/clipboard_util.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/message_loop.h" |
| 15 #include "base/string_util.h" | 16 #include "base/string_util.h" |
| 16 | 17 |
| 17 namespace { | 18 namespace { |
| 18 | 19 |
| 19 // A scoper to manage acquiring and automatically releasing the clipboard. | 20 // A scoper to manage acquiring and automatically releasing the clipboard. |
| 20 class ScopedClipboard { | 21 class ScopedClipboard { |
| 21 public: | 22 public: |
| 22 ScopedClipboard() : opened_(false) { } | 23 ScopedClipboard() : opened_(false) { } |
| 23 | 24 |
| 24 ~ScopedClipboard() { | 25 ~ScopedClipboard() { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 private: | 76 private: |
| 76 bool opened_; | 77 bool opened_; |
| 77 }; | 78 }; |
| 78 | 79 |
| 79 LRESULT CALLBACK ClipboardOwnerWndProc(HWND hwnd, | 80 LRESULT CALLBACK ClipboardOwnerWndProc(HWND hwnd, |
| 80 UINT message, | 81 UINT message, |
| 81 WPARAM wparam, | 82 WPARAM wparam, |
| 82 LPARAM lparam) { | 83 LPARAM lparam) { |
| 83 LRESULT lresult = 0; | 84 LRESULT lresult = 0; |
| 84 | 85 |
| 85 switch(message) { | 86 switch (message) { |
| 86 case WM_RENDERFORMAT: | 87 case WM_RENDERFORMAT: |
| 87 // This message comes when SetClipboardData was sent a null data handle | 88 // This message comes when SetClipboardData was sent a null data handle |
| 88 // and now it's come time to put the data on the clipboard. | 89 // and now it's come time to put the data on the clipboard. |
| 89 // We always set data, so there isn't a need to actually do anything here. | 90 // We always set data, so there isn't a need to actually do anything here. |
| 90 break; | 91 break; |
| 91 case WM_RENDERALLFORMATS: | 92 case WM_RENDERALLFORMATS: |
| 92 // This message comes when SetClipboardData was sent a null data handle | 93 // This message comes when SetClipboardData was sent a null data handle |
| 93 // and now this application is about to quit, so it must put data on | 94 // and now this application is about to quit, so it must put data on |
| 94 // the clipboard before it exits. | 95 // the clipboard before it exits. |
| 95 // We always set data, so there isn't a need to actually do anything here. | 96 // We always set data, so there isn't a need to actually do anything here. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 115 charT* raw_data = static_cast<charT*>(::GlobalLock(data)); | 116 charT* raw_data = static_cast<charT*>(::GlobalLock(data)); |
| 116 memcpy(raw_data, str.data(), str.size() * sizeof(charT)); | 117 memcpy(raw_data, str.data(), str.size() * sizeof(charT)); |
| 117 raw_data[str.size()] = '\0'; | 118 raw_data[str.size()] = '\0'; |
| 118 ::GlobalUnlock(data); | 119 ::GlobalUnlock(data); |
| 119 } | 120 } |
| 120 return data; | 121 return data; |
| 121 }; | 122 }; |
| 122 | 123 |
| 123 } // namespace | 124 } // namespace |
| 124 | 125 |
| 125 Clipboard::Clipboard() { | 126 Clipboard::Clipboard() : create_window_(false) { |
| 126 // make a dummy HWND to be the clipboard's owner | 127 if (MessageLoop::current()->type() == MessageLoop::TYPE_UI) { |
| 127 WNDCLASSEX wcex = {0}; | 128 // Make a dummy HWND to be the clipboard's owner. |
| 128 wcex.cbSize = sizeof(WNDCLASSEX); | 129 WNDCLASSEX wcex = {0}; |
| 129 wcex.lpfnWndProc = ClipboardOwnerWndProc; | 130 wcex.cbSize = sizeof(WNDCLASSEX); |
| 130 wcex.hInstance = GetModuleHandle(NULL); | 131 wcex.lpfnWndProc = ClipboardOwnerWndProc; |
| 131 wcex.lpszClassName = L"ClipboardOwnerWindowClass"; | 132 wcex.hInstance = GetModuleHandle(NULL); |
| 132 ::RegisterClassEx(&wcex); | 133 wcex.lpszClassName = L"ClipboardOwnerWindowClass"; |
| 134 ::RegisterClassEx(&wcex); |
| 135 create_window_ = true; |
| 136 } |
| 133 | 137 |
| 134 clipboard_owner_ = NULL; | 138 clipboard_owner_ = NULL; |
| 135 } | 139 } |
| 136 | 140 |
| 137 Clipboard::~Clipboard() { | 141 Clipboard::~Clipboard() { |
| 138 if (clipboard_owner_) | 142 if (clipboard_owner_) |
| 139 ::DestroyWindow(clipboard_owner_); | 143 ::DestroyWindow(clipboard_owner_); |
| 140 clipboard_owner_ = NULL; | 144 clipboard_owner_ = NULL; |
| 141 } | 145 } |
| 142 | 146 |
| 143 void Clipboard::WriteObjects(const ObjectMap& objects) { | 147 void Clipboard::WriteObjects(const ObjectMap& objects) { |
| 144 WriteObjects(objects, NULL); | 148 WriteObjects(objects, NULL); |
| 145 } | 149 } |
| 146 | 150 |
| 147 void Clipboard::WriteObjects(const ObjectMap& objects, | 151 void Clipboard::WriteObjects(const ObjectMap& objects, |
| 148 base::ProcessHandle process) { | 152 base::ProcessHandle process) { |
| 149 ScopedClipboard clipboard; | 153 ScopedClipboard clipboard; |
| 150 if (!clipboard.Acquire(GetClipboardWindow())) | 154 if (!clipboard.Acquire(GetClipboardWindow())) |
| 151 return; | 155 return; |
| 152 | 156 |
| 153 ::EmptyClipboard(); | 157 ::EmptyClipboard(); |
| 154 | 158 |
| 155 for (ObjectMap::const_iterator iter = objects.begin(); | 159 for (ObjectMap::const_iterator iter = objects.begin(); |
| 156 iter != objects.end(); ++iter) { | 160 iter != objects.end(); ++iter) { |
| 157 if (iter->first == CBF_SMBITMAP) | 161 if (iter->first == CBF_SMBITMAP) |
| 158 WriteBitmapFromSharedMemory(&(iter->second[0].front()), | 162 WriteBitmapFromSharedMemory(&(iter->second[0].front()), |
| 159 &(iter->second[1].front()), | 163 &(iter->second[1].front()), |
| 160 process); | 164 process); |
| 161 else | 165 else |
| 162 DispatchObject(static_cast<ObjectType>(iter->first), iter->second); | 166 DispatchObject(static_cast<ObjectType>(iter->first), iter->second); |
| 163 } | 167 } |
| 164 } | 168 } |
| 165 | 169 |
| 166 void Clipboard::WriteText(const char* text_data, size_t text_len) { | 170 void Clipboard::WriteText(const char* text_data, size_t text_len) { |
| 167 std::wstring text; | 171 std::wstring text; |
| 168 UTF8ToWide(text_data, text_len, &text); | 172 UTF8ToWide(text_data, text_len, &text); |
| 169 HGLOBAL glob = CreateGlobalData(text); | 173 HGLOBAL glob = CreateGlobalData(text); |
| 170 | 174 |
| 171 WriteToClipboard(CF_UNICODETEXT, glob); | 175 WriteToClipboard(CF_UNICODETEXT, glob); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 link.append(url); | 220 link.append(url); |
| 217 link.append("\">"); | 221 link.append("\">"); |
| 218 link.append(title); | 222 link.append(title); |
| 219 link.append("</a>"); | 223 link.append("</a>"); |
| 220 | 224 |
| 221 // Store hyperlink as html. | 225 // Store hyperlink as html. |
| 222 WriteHTML(link.c_str(), link.size(), NULL, 0); | 226 WriteHTML(link.c_str(), link.size(), NULL, 0); |
| 223 } | 227 } |
| 224 | 228 |
| 225 void Clipboard::WriteWebSmartPaste() { | 229 void Clipboard::WriteWebSmartPaste() { |
| 230 DCHECK(clipboard_owner_); |
| 226 ::SetClipboardData(GetWebKitSmartPasteFormatType(), NULL); | 231 ::SetClipboardData(GetWebKitSmartPasteFormatType(), NULL); |
| 227 } | 232 } |
| 228 | 233 |
| 229 void Clipboard::WriteBitmap(const char* pixel_data, const char* size_data) { | 234 void Clipboard::WriteBitmap(const char* pixel_data, const char* size_data) { |
| 230 const gfx::Size* size = reinterpret_cast<const gfx::Size*>(size_data); | 235 const gfx::Size* size = reinterpret_cast<const gfx::Size*>(size_data); |
| 231 HDC dc = ::GetDC(NULL); | 236 HDC dc = ::GetDC(NULL); |
| 232 | 237 |
| 233 // This doesn't actually cost us a memcpy when the bitmap comes from the | 238 // This doesn't actually cost us a memcpy when the bitmap comes from the |
| 234 // renderer as we load it into the bitmap using setPixels which just sets a | 239 // renderer as we load it into the bitmap using setPixels which just sets a |
| 235 // pointer. Someone has to memcpy it into GDI, it might as well be us here. | 240 // pointer. Someone has to memcpy it into GDI, it might as well be us here. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 258 WriteBitmapFromHandle(source_hbitmap, *size); | 263 WriteBitmapFromHandle(source_hbitmap, *size); |
| 259 } | 264 } |
| 260 | 265 |
| 261 ::DeleteObject(source_hbitmap); | 266 ::DeleteObject(source_hbitmap); |
| 262 ::ReleaseDC(NULL, dc); | 267 ::ReleaseDC(NULL, dc); |
| 263 } | 268 } |
| 264 | 269 |
| 265 void Clipboard::WriteBitmapFromSharedMemory(const char* bitmap_data, | 270 void Clipboard::WriteBitmapFromSharedMemory(const char* bitmap_data, |
| 266 const char* size_data, | 271 const char* size_data, |
| 267 base::ProcessHandle process) { | 272 base::ProcessHandle process) { |
| 268 const base::SharedMemoryHandle* remote_bitmap_handle = | |
| 269 reinterpret_cast<const base::SharedMemoryHandle*>(bitmap_data); | |
| 270 const gfx::Size* size = reinterpret_cast<const gfx::Size*>(size_data); | 273 const gfx::Size* size = reinterpret_cast<const gfx::Size*>(size_data); |
| 271 | 274 |
| 272 base::SharedMemory bitmap(*remote_bitmap_handle, false, process); | 275 // bitmap_data has an encoded shared memory object. See |
| 276 // DuplicateRemoteHandles(). |
| 277 char* ptr = const_cast<char*>(bitmap_data); |
| 278 scoped_ptr<const base::SharedMemory> bitmap(* |
| 279 reinterpret_cast<const base::SharedMemory**>(ptr)); |
| 273 | 280 |
| 274 // TODO(darin): share data in gfx/bitmap_header.cc somehow | 281 // TODO(darin): share data in gfx/bitmap_header.cc somehow. |
| 275 BITMAPINFO bm_info = {0}; | 282 BITMAPINFO bm_info = {0}; |
| 276 bm_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); | 283 bm_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); |
| 277 bm_info.bmiHeader.biWidth = size->width(); | 284 bm_info.bmiHeader.biWidth = size->width(); |
| 278 bm_info.bmiHeader.biHeight = -size->height(); // Sets the vertical orientatio
n | 285 bm_info.bmiHeader.biHeight = -size->height(); // Sets the vertical orientatio
n |
| 279 bm_info.bmiHeader.biPlanes = 1; | 286 bm_info.bmiHeader.biPlanes = 1; |
| 280 bm_info.bmiHeader.biBitCount = 32; | 287 bm_info.bmiHeader.biBitCount = 32; |
| 281 bm_info.bmiHeader.biCompression = BI_RGB; | 288 bm_info.bmiHeader.biCompression = BI_RGB; |
| 282 | 289 |
| 283 HDC dc = ::GetDC(NULL); | 290 HDC dc = ::GetDC(NULL); |
| 284 | 291 |
| 285 // We can create an HBITMAP directly using the shared memory handle, saving | 292 // We can create an HBITMAP directly using the shared memory handle, saving |
| 286 // a memcpy. | 293 // a memcpy. |
| 287 HBITMAP source_hbitmap = | 294 HBITMAP source_hbitmap = |
| 288 ::CreateDIBSection(dc, &bm_info, DIB_RGB_COLORS, NULL, | 295 ::CreateDIBSection(dc, &bm_info, DIB_RGB_COLORS, NULL, |
| 289 bitmap.handle(), 0); | 296 bitmap->handle(), 0); |
| 290 | 297 |
| 291 if (source_hbitmap) { | 298 if (source_hbitmap) { |
| 292 // Now we can write the HBITMAP to the clipboard | 299 // Now we can write the HBITMAP to the clipboard |
| 293 WriteBitmapFromHandle(source_hbitmap, *size); | 300 WriteBitmapFromHandle(source_hbitmap, *size); |
| 294 } | 301 } |
| 295 | 302 |
| 296 ::DeleteObject(source_hbitmap); | 303 ::DeleteObject(source_hbitmap); |
| 297 ::ReleaseDC(NULL, dc); | 304 ::ReleaseDC(NULL, dc); |
| 298 } | 305 } |
| 299 | 306 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 drop_files->fWide = TRUE; | 364 drop_files->fWide = TRUE; |
| 358 | 365 |
| 359 memcpy(data + sizeof DROPFILES, filenames.c_str(), | 366 memcpy(data + sizeof DROPFILES, filenames.c_str(), |
| 360 filenames.length() * sizeof(wchar_t)); | 367 filenames.length() * sizeof(wchar_t)); |
| 361 | 368 |
| 362 ::GlobalUnlock(hdata); | 369 ::GlobalUnlock(hdata); |
| 363 WriteToClipboard(CF_HDROP, hdata); | 370 WriteToClipboard(CF_HDROP, hdata); |
| 364 } | 371 } |
| 365 | 372 |
| 366 void Clipboard::WriteToClipboard(FormatType format, HANDLE handle) { | 373 void Clipboard::WriteToClipboard(FormatType format, HANDLE handle) { |
| 367 if (handle && !::SetClipboardData(format, handle)) | 374 DCHECK(clipboard_owner_); |
| 375 if (handle && !::SetClipboardData(format, handle)) { |
| 376 DCHECK(ERROR_CLIPBOARD_NOT_OPEN != GetLastError()); |
| 368 FreeData(format, handle); | 377 FreeData(format, handle); |
| 378 } |
| 369 } | 379 } |
| 370 | 380 |
| 371 bool Clipboard::IsFormatAvailable(unsigned int format) const { | 381 bool Clipboard::IsFormatAvailable(unsigned int format) const { |
| 372 return ::IsClipboardFormatAvailable(format) != FALSE; | 382 return ::IsClipboardFormatAvailable(format) != FALSE; |
| 373 } | 383 } |
| 374 | 384 |
| 375 void Clipboard::ReadText(std::wstring* result) const { | 385 void Clipboard::ReadText(std::wstring* result) const { |
| 376 if (!result) { | 386 if (!result) { |
| 377 NOTREACHED(); | 387 NOTREACHED(); |
| 378 return; | 388 return; |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 584 Clipboard::FormatType Clipboard::GetFileDescriptorFormatType() { | 594 Clipboard::FormatType Clipboard::GetFileDescriptorFormatType() { |
| 585 return ClipboardUtil::GetFileDescriptorFormat()->cfFormat; | 595 return ClipboardUtil::GetFileDescriptorFormat()->cfFormat; |
| 586 } | 596 } |
| 587 | 597 |
| 588 // static | 598 // static |
| 589 Clipboard::FormatType Clipboard::GetFileContentFormatZeroType() { | 599 Clipboard::FormatType Clipboard::GetFileContentFormatZeroType() { |
| 590 return ClipboardUtil::GetFileContentFormatZero()->cfFormat; | 600 return ClipboardUtil::GetFileContentFormatZero()->cfFormat; |
| 591 } | 601 } |
| 592 | 602 |
| 593 // static | 603 // static |
| 604 void Clipboard::DuplicateRemoteHandles(base::ProcessHandle process, |
| 605 ObjectMap* objects) { |
| 606 for (ObjectMap::iterator iter = objects->begin(); iter != objects->end(); |
| 607 ++iter) { |
| 608 if (iter->first == CBF_SMBITMAP) { |
| 609 // There is a shared memory handle encoded on the first ObjectMapParam. |
| 610 // Use it to open a local handle to the memory. |
| 611 char* bitmap_data = &(iter->second[0].front()); |
| 612 base::SharedMemoryHandle* remote_bitmap_handle = |
| 613 reinterpret_cast<base::SharedMemoryHandle*>(bitmap_data); |
| 614 |
| 615 base::SharedMemory* bitmap = new base::SharedMemory(*remote_bitmap_handle, |
| 616 false, process); |
| 617 |
| 618 // We store the object where the remote handle was located so it can |
| 619 // be retrieved by the UI thread (see WriteBitmapFromSharedMemory()). |
| 620 iter->second[0].clear(); |
| 621 for (size_t i = 0; i < sizeof(bitmap); i++) |
| 622 iter->second[0].push_back(reinterpret_cast<char*>(&bitmap)[i]); |
| 623 } |
| 624 } |
| 625 } |
| 626 |
| 627 // static |
| 594 Clipboard::FormatType Clipboard::GetWebKitSmartPasteFormatType() { | 628 Clipboard::FormatType Clipboard::GetWebKitSmartPasteFormatType() { |
| 595 return ClipboardUtil::GetWebKitSmartPasteFormat()->cfFormat; | 629 return ClipboardUtil::GetWebKitSmartPasteFormat()->cfFormat; |
| 596 } | 630 } |
| 597 | 631 |
| 598 // static | 632 // static |
| 599 void Clipboard::FreeData(FormatType format, HANDLE data) { | 633 void Clipboard::FreeData(FormatType format, HANDLE data) { |
| 600 if (format == CF_BITMAP) | 634 if (format == CF_BITMAP) |
| 601 ::DeleteObject(static_cast<HBITMAP>(data)); | 635 ::DeleteObject(static_cast<HBITMAP>(data)); |
| 602 else | 636 else |
| 603 ::GlobalFree(data); | 637 ::GlobalFree(data); |
| 604 } | 638 } |
| 605 | 639 |
| 606 HWND Clipboard::GetClipboardWindow() const { | 640 HWND Clipboard::GetClipboardWindow() const { |
| 607 if (!clipboard_owner_) { | 641 if (!clipboard_owner_ && create_window_) { |
| 608 clipboard_owner_ = ::CreateWindow(L"ClipboardOwnerWindowClass", | 642 clipboard_owner_ = ::CreateWindow(L"ClipboardOwnerWindowClass", |
| 609 L"ClipboardOwnerWindow", | 643 L"ClipboardOwnerWindow", |
| 610 0, 0, 0, 0, 0, | 644 0, 0, 0, 0, 0, |
| 611 HWND_MESSAGE, | 645 HWND_MESSAGE, |
| 612 0, 0, 0); | 646 0, 0, 0); |
| 613 } | 647 } |
| 614 return clipboard_owner_; | 648 return clipboard_owner_; |
| 615 } | 649 } |
| OLD | NEW |