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

Side by Side Diff: base/clipboard_win.cc

Issue 19733: Make sure that Clipboard operations that require dispatching... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW
« base/clipboard.h ('K') | « base/clipboard_unittest.cc ('k') | base/file_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698