Chromium Code Reviews| 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.h" |
| 9 | 9 |
| 10 #include <shlobj.h> | 10 #include <shlobj.h> |
| 11 #include <shellapi.h> | 11 #include <shellapi.h> |
| 12 | 12 |
| 13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
| 14 #include "base/files/file_path.h" | 14 #include "base/files/file_path.h" |
| 15 #include "base/logging.h" | 15 #include "base/logging.h" |
| 16 #include "base/memory/shared_memory.h" | 16 #include "base/memory/shared_memory.h" |
| 17 #include "base/message_loop.h" | 17 #include "base/message_loop.h" |
| 18 #include "base/safe_numerics.h" | 18 #include "base/safe_numerics.h" |
| 19 #include "base/stl_util.h" | 19 #include "base/stl_util.h" |
| 20 #include "base/strings/string_number_conversions.h" | 20 #include "base/strings/string_number_conversions.h" |
| 21 #include "base/strings/string_util.h" | 21 #include "base/strings/string_util.h" |
| 22 #include "base/strings/utf_offset_string_conversions.h" | 22 #include "base/strings/utf_offset_string_conversions.h" |
| 23 #include "base/strings/utf_string_conversions.h" | 23 #include "base/strings/utf_string_conversions.h" |
| 24 #include "base/win/message_window.h" | |
| 24 #include "base/win/scoped_gdi_object.h" | 25 #include "base/win/scoped_gdi_object.h" |
| 25 #include "base/win/scoped_hdc.h" | 26 #include "base/win/scoped_hdc.h" |
| 26 #include "base/win/wrapped_window_proc.h" | 27 #include "base/win/wrapped_window_proc.h" |
| 27 #include "third_party/skia/include/core/SkBitmap.h" | 28 #include "third_party/skia/include/core/SkBitmap.h" |
| 28 #include "ui/base/clipboard/clipboard_util_win.h" | 29 #include "ui/base/clipboard/clipboard_util_win.h" |
| 29 #include "ui/base/clipboard/custom_data_helper.h" | 30 #include "ui/base/clipboard/custom_data_helper.h" |
| 30 #include "ui/gfx/canvas.h" | 31 #include "ui/gfx/canvas.h" |
| 31 #include "ui/gfx/size.h" | 32 #include "ui/gfx/size.h" |
| 32 | 33 |
| 33 namespace ui { | 34 namespace ui { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 87 opened_ = false; | 88 opened_ = false; |
| 88 } else { | 89 } else { |
| 89 NOTREACHED(); | 90 NOTREACHED(); |
| 90 } | 91 } |
| 91 } | 92 } |
| 92 | 93 |
| 93 private: | 94 private: |
| 94 bool opened_; | 95 bool opened_; |
| 95 }; | 96 }; |
| 96 | 97 |
| 97 LRESULT CALLBACK ClipboardOwnerWndProc(HWND hwnd, | |
| 98 UINT message, | |
| 99 WPARAM wparam, | |
| 100 LPARAM lparam) { | |
| 101 LRESULT lresult = 0; | |
| 102 | |
| 103 switch (message) { | |
| 104 case WM_RENDERFORMAT: | |
| 105 // This message comes when SetClipboardData was sent a null data handle | |
| 106 // and now it's come time to put the data on the clipboard. | |
| 107 // We always set data, so there isn't a need to actually do anything here. | |
| 108 break; | |
| 109 case WM_RENDERALLFORMATS: | |
| 110 // This message comes when SetClipboardData was sent a null data handle | |
| 111 // and now this application is about to quit, so it must put data on | |
| 112 // the clipboard before it exits. | |
| 113 // We always set data, so there isn't a need to actually do anything here. | |
| 114 break; | |
| 115 case WM_DRAWCLIPBOARD: | |
| 116 break; | |
| 117 case WM_DESTROY: | |
| 118 break; | |
| 119 case WM_CHANGECBCHAIN: | |
| 120 break; | |
| 121 default: | |
| 122 lresult = DefWindowProc(hwnd, message, wparam, lparam); | |
| 123 break; | |
| 124 } | |
| 125 return lresult; | |
| 126 } | |
| 127 | |
| 128 template <typename charT> | 98 template <typename charT> |
| 129 HGLOBAL CreateGlobalData(const std::basic_string<charT>& str) { | 99 HGLOBAL CreateGlobalData(const std::basic_string<charT>& str) { |
| 130 HGLOBAL data = | 100 HGLOBAL data = |
| 131 ::GlobalAlloc(GMEM_MOVEABLE, ((str.size() + 1) * sizeof(charT))); | 101 ::GlobalAlloc(GMEM_MOVEABLE, ((str.size() + 1) * sizeof(charT))); |
| 132 if (data) { | 102 if (data) { |
| 133 charT* raw_data = static_cast<charT*>(::GlobalLock(data)); | 103 charT* raw_data = static_cast<charT*>(::GlobalLock(data)); |
| 134 memcpy(raw_data, str.data(), str.size() * sizeof(charT)); | 104 memcpy(raw_data, str.data(), str.size() * sizeof(charT)); |
| 135 raw_data[str.size()] = '\0'; | 105 raw_data[str.size()] = '\0'; |
| 136 ::GlobalUnlock(data); | 106 ::GlobalUnlock(data); |
| 137 } | 107 } |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 154 void MakeBitmapOpaque(const SkBitmap& bitmap) { | 124 void MakeBitmapOpaque(const SkBitmap& bitmap) { |
| 155 for (int x = 0; x < bitmap.width(); ++x) { | 125 for (int x = 0; x < bitmap.width(); ++x) { |
| 156 for (int y = 0; y < bitmap.height(); ++y) { | 126 for (int y = 0; y < bitmap.height(); ++y) { |
| 157 *bitmap.getAddr32(x, y) = SkColorSetA(*bitmap.getAddr32(x, y), 0xFF); | 127 *bitmap.getAddr32(x, y) = SkColorSetA(*bitmap.getAddr32(x, y), 0xFF); |
| 158 } | 128 } |
| 159 } | 129 } |
| 160 } | 130 } |
| 161 | 131 |
| 162 } // namespace | 132 } // namespace |
| 163 | 133 |
| 134 // Used to create a message-only window handling clipboard-related window | |
| 135 // messages. It is intended to be passed to OpenClipboard() API. | |
| 136 class Clipboard::ClipboardWindow | |
| 137 : public base::win::MessageWindow::Delegate { | |
| 138 public: | |
| 139 ClipboardWindow(); | |
| 140 virtual ~ClipboardWindow(); | |
| 141 | |
| 142 // Creates the window if it is not created yat and returns its handle. Returns | |
| 143 // NULL if an error occurs. | |
| 144 HWND GetHandle(); | |
| 145 | |
| 146 // Returns |true| if the window is created. | |
| 147 bool IsValid() const; | |
| 148 | |
| 149 private: | |
| 150 // base::win::MessageWindow::Delegate interface. | |
| 151 virtual bool HandleMessage(HWND hwnd, | |
| 152 UINT message, | |
| 153 WPARAM wparam, | |
| 154 LPARAM lparam, | |
| 155 LRESULT* result) OVERRIDE; | |
| 156 | |
| 157 scoped_ptr<base::win::MessageWindow> window_; | |
|
cpu_(ooo_6.6-7.5)
2013/06/19 00:11:36
why scoped_ptr?
alexeypa (please no reviews)
2013/06/19 17:57:18
Yes, indeed. It does not need to be.
| |
| 158 | |
| 159 DISALLOW_COPY_AND_ASSIGN(ClipboardWindow); | |
| 160 }; | |
| 161 | |
| 162 | |
| 163 Clipboard::ClipboardWindow::ClipboardWindow() | |
| 164 : window_(new base::win::MessageWindow()) { | |
| 165 } | |
| 166 | |
| 167 Clipboard::ClipboardWindow::~ClipboardWindow() { | |
| 168 } | |
| 169 | |
| 170 HWND Clipboard::ClipboardWindow::GetHandle() { | |
| 171 if (!IsValid()) | |
| 172 window_->Create(this); | |
| 173 | |
| 174 return window_->hwnd(); | |
| 175 } | |
| 176 | |
| 177 bool Clipboard::ClipboardWindow::IsValid() const { | |
| 178 return window_->hwnd() != NULL; | |
| 179 } | |
| 180 | |
| 181 bool Clipboard::ClipboardWindow::HandleMessage(HWND hwnd, | |
| 182 UINT message, | |
| 183 WPARAM wparam, | |
| 184 LPARAM lparam, | |
| 185 LRESULT* result) { | |
| 186 switch (message) { | |
| 187 case WM_RENDERFORMAT: | |
| 188 // This message comes when SetClipboardData was sent a null data handle | |
| 189 // and now it's come time to put the data on the clipboard. | |
| 190 // We always set data, so there isn't a need to actually do anything here. | |
| 191 break; | |
| 192 case WM_RENDERALLFORMATS: | |
| 193 // This message comes when SetClipboardData was sent a null data handle | |
| 194 // and now this application is about to quit, so it must put data on | |
| 195 // the clipboard before it exits. | |
| 196 // We always set data, so there isn't a need to actually do anything here. | |
| 197 break; | |
| 198 case WM_DRAWCLIPBOARD: | |
| 199 break; | |
| 200 case WM_DESTROY: | |
| 201 break; | |
| 202 case WM_CHANGECBCHAIN: | |
| 203 break; | |
| 204 default: | |
| 205 return false; | |
| 206 } | |
| 207 | |
| 208 *result = 0; | |
| 209 return true; | |
| 210 } | |
| 211 | |
| 164 Clipboard::FormatType::FormatType() : data_() {} | 212 Clipboard::FormatType::FormatType() : data_() {} |
| 165 | 213 |
| 166 Clipboard::FormatType::FormatType(UINT native_format) : data_() { | 214 Clipboard::FormatType::FormatType(UINT native_format) : data_() { |
| 167 // There's no good way to actually initialize this in the constructor in | 215 // There's no good way to actually initialize this in the constructor in |
| 168 // C++03. | 216 // C++03. |
| 169 data_.cfFormat = native_format; | 217 data_.cfFormat = native_format; |
| 170 data_.dwAspect = DVASPECT_CONTENT; | 218 data_.dwAspect = DVASPECT_CONTENT; |
| 171 data_.lindex = -1; | 219 data_.lindex = -1; |
| 172 data_.tymed = TYMED_HGLOBAL; | 220 data_.tymed = TYMED_HGLOBAL; |
| 173 } | 221 } |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 196 NOTREACHED(); | 244 NOTREACHED(); |
| 197 return FormatType(); | 245 return FormatType(); |
| 198 } | 246 } |
| 199 return FormatType(clipboard_format); | 247 return FormatType(clipboard_format); |
| 200 } | 248 } |
| 201 | 249 |
| 202 bool Clipboard::FormatType::operator<(const FormatType& other) const { | 250 bool Clipboard::FormatType::operator<(const FormatType& other) const { |
| 203 return ToUINT() < other.ToUINT(); | 251 return ToUINT() < other.ToUINT(); |
| 204 } | 252 } |
| 205 | 253 |
| 206 Clipboard::Clipboard() : create_window_(false) { | 254 Clipboard::Clipboard() { |
| 207 if (base::MessageLoop::current()->type() == base::MessageLoop::TYPE_UI) { | 255 if (base::MessageLoop::current()->type() == base::MessageLoop::TYPE_UI) |
| 208 // Make a dummy HWND to be the clipboard's owner. | 256 clipboard_owner_.reset(new ClipboardWindow()); |
| 209 WNDCLASSEX window_class; | |
| 210 base::win::InitializeWindowClass( | |
| 211 L"ClipboardOwnerWindowClass", | |
| 212 &base::win::WrappedWindowProc<ClipboardOwnerWndProc>, | |
| 213 0, 0, 0, NULL, NULL, NULL, NULL, NULL, | |
| 214 &window_class); | |
| 215 ::RegisterClassEx(&window_class); | |
| 216 create_window_ = true; | |
| 217 } | |
| 218 | |
| 219 clipboard_owner_ = NULL; | |
| 220 } | 257 } |
| 221 | 258 |
| 222 Clipboard::~Clipboard() { | 259 Clipboard::~Clipboard() { |
| 223 if (clipboard_owner_) | |
| 224 ::DestroyWindow(clipboard_owner_); | |
| 225 clipboard_owner_ = NULL; | |
| 226 } | 260 } |
| 227 | 261 |
| 228 void Clipboard::WriteObjects(Buffer buffer, const ObjectMap& objects) { | 262 void Clipboard::WriteObjects(Buffer buffer, const ObjectMap& objects) { |
| 229 DCHECK_EQ(buffer, BUFFER_STANDARD); | 263 DCHECK_EQ(buffer, BUFFER_STANDARD); |
| 230 | 264 |
| 231 ScopedClipboard clipboard; | 265 ScopedClipboard clipboard; |
| 232 if (!clipboard.Acquire(GetClipboardWindow())) | 266 if (!clipboard.Acquire(GetClipboardWindow())) |
| 233 return; | 267 return; |
| 234 | 268 |
| 235 ::EmptyClipboard(); | 269 ::EmptyClipboard(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 276 bookmark.append(1, L'\n'); | 310 bookmark.append(1, L'\n'); |
| 277 bookmark.append(url_data, url_len); | 311 bookmark.append(url_data, url_len); |
| 278 | 312 |
| 279 string16 wide_bookmark = UTF8ToWide(bookmark); | 313 string16 wide_bookmark = UTF8ToWide(bookmark); |
| 280 HGLOBAL glob = CreateGlobalData(wide_bookmark); | 314 HGLOBAL glob = CreateGlobalData(wide_bookmark); |
| 281 | 315 |
| 282 WriteToClipboard(GetUrlWFormatType().ToUINT(), glob); | 316 WriteToClipboard(GetUrlWFormatType().ToUINT(), glob); |
| 283 } | 317 } |
| 284 | 318 |
| 285 void Clipboard::WriteWebSmartPaste() { | 319 void Clipboard::WriteWebSmartPaste() { |
| 286 DCHECK(clipboard_owner_); | 320 DCHECK(clipboard_owner_->IsValid()); |
| 287 ::SetClipboardData(GetWebKitSmartPasteFormatType().ToUINT(), NULL); | 321 ::SetClipboardData(GetWebKitSmartPasteFormatType().ToUINT(), NULL); |
| 288 } | 322 } |
| 289 | 323 |
| 290 void Clipboard::WriteBitmap(const char* pixel_data, const char* size_data) { | 324 void Clipboard::WriteBitmap(const char* pixel_data, const char* size_data) { |
| 291 const gfx::Size* size = reinterpret_cast<const gfx::Size*>(size_data); | 325 const gfx::Size* size = reinterpret_cast<const gfx::Size*>(size_data); |
| 292 HDC dc = ::GetDC(NULL); | 326 HDC dc = ::GetDC(NULL); |
| 293 | 327 |
| 294 // This doesn't actually cost us a memcpy when the bitmap comes from the | 328 // This doesn't actually cost us a memcpy when the bitmap comes from the |
| 295 // renderer as we load it into the bitmap using setPixels which just sets a | 329 // renderer as we load it into the bitmap using setPixels which just sets a |
| 296 // pointer. Someone has to memcpy it into GDI, it might as well be us here. | 330 // pointer. Someone has to memcpy it into GDI, it might as well be us here. |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 371 if (!hdata) | 405 if (!hdata) |
| 372 return; | 406 return; |
| 373 | 407 |
| 374 char* data = static_cast<char*>(::GlobalLock(hdata)); | 408 char* data = static_cast<char*>(::GlobalLock(hdata)); |
| 375 memcpy(data, data_data, data_len); | 409 memcpy(data, data_data, data_len); |
| 376 ::GlobalUnlock(data); | 410 ::GlobalUnlock(data); |
| 377 WriteToClipboard(format.ToUINT(), hdata); | 411 WriteToClipboard(format.ToUINT(), hdata); |
| 378 } | 412 } |
| 379 | 413 |
| 380 void Clipboard::WriteToClipboard(unsigned int format, HANDLE handle) { | 414 void Clipboard::WriteToClipboard(unsigned int format, HANDLE handle) { |
| 381 DCHECK(clipboard_owner_); | 415 DCHECK(clipboard_owner_->IsValid()); |
| 382 if (handle && !::SetClipboardData(format, handle)) { | 416 if (handle && !::SetClipboardData(format, handle)) { |
| 383 DCHECK(ERROR_CLIPBOARD_NOT_OPEN != GetLastError()); | 417 DCHECK(ERROR_CLIPBOARD_NOT_OPEN != GetLastError()); |
| 384 FreeData(format, handle); | 418 FreeData(format, handle); |
| 385 } | 419 } |
| 386 } | 420 } |
| 387 | 421 |
| 388 uint64 Clipboard::GetSequenceNumber(Buffer buffer) { | 422 uint64 Clipboard::GetSequenceNumber(Buffer buffer) { |
| 389 DCHECK_EQ(buffer, BUFFER_STANDARD); | 423 DCHECK_EQ(buffer, BUFFER_STANDARD); |
| 390 return ::GetClipboardSequenceNumber(); | 424 return ::GetClipboardSequenceNumber(); |
| 391 } | 425 } |
| (...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 818 | 852 |
| 819 // static | 853 // static |
| 820 void Clipboard::FreeData(unsigned int format, HANDLE data) { | 854 void Clipboard::FreeData(unsigned int format, HANDLE data) { |
| 821 if (format == CF_BITMAP) | 855 if (format == CF_BITMAP) |
| 822 ::DeleteObject(static_cast<HBITMAP>(data)); | 856 ::DeleteObject(static_cast<HBITMAP>(data)); |
| 823 else | 857 else |
| 824 ::GlobalFree(data); | 858 ::GlobalFree(data); |
| 825 } | 859 } |
| 826 | 860 |
| 827 HWND Clipboard::GetClipboardWindow() const { | 861 HWND Clipboard::GetClipboardWindow() const { |
| 828 if (!clipboard_owner_ && create_window_) { | 862 return clipboard_owner_ ? clipboard_owner_->GetHandle() : NULL; |
| 829 clipboard_owner_ = ::CreateWindow(L"ClipboardOwnerWindowClass", | |
| 830 L"ClipboardOwnerWindow", | |
| 831 0, 0, 0, 0, 0, | |
| 832 HWND_MESSAGE, | |
| 833 0, 0, 0); | |
| 834 } | |
| 835 return clipboard_owner_; | |
| 836 } | 863 } |
| 837 | 864 |
| 838 } // namespace ui | 865 } // namespace ui |
| OLD | NEW |